
package com.joysuch.wwyt.monitoringcenter.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.joysuch.wwyt.api.basedata.service.BaseImageSyncService;
import com.joysuch.wwyt.bp.entity.BpDepart;
import com.joysuch.wwyt.bp.entity.BpWorkType;
import com.joysuch.wwyt.bp.entity.contractor.BpContractorStaff;
import com.joysuch.wwyt.bp.enums.DataStateTypes;
import com.joysuch.wwyt.bp.repository.*;
import com.joysuch.wwyt.config.RedisClient;
import com.joysuch.wwyt.core.bean.BaseAttachmentBean;
import com.joysuch.wwyt.core.common.ajax.ResultBean;
import com.joysuch.wwyt.core.common.util.DateTimeUtil;
import com.joysuch.wwyt.core.common.util.JsonUtil;
import com.joysuch.wwyt.core.common.util.SimpleDateFormatCache;
import com.joysuch.wwyt.core.entity.BaseConfig;
import com.joysuch.wwyt.core.entity.BaseImageRepository;
import com.joysuch.wwyt.core.entity.BaseUser;
import com.joysuch.wwyt.core.enums.BaseConfigCodes;
import com.joysuch.wwyt.core.enums.BaseIdCardTypes;
import com.joysuch.wwyt.core.enums.Status;
import com.joysuch.wwyt.core.repository.BaseImageRespositoryDao;
import com.joysuch.wwyt.core.repository.BaseLoginAccountDao;
import com.joysuch.wwyt.core.repository.BaseTypeGroupItemDao;
import com.joysuch.wwyt.core.repository.BaseUserDao;
import com.joysuch.wwyt.core.security.ShiroUser;
import com.joysuch.wwyt.core.service.BaseConfigService;
import com.joysuch.wwyt.core.support.Context;
import com.joysuch.wwyt.dzhapi.bean.*;
import com.joysuch.wwyt.dzhapi.dto.BuildDataDto;
import com.joysuch.wwyt.dzhapi.mapper.*;
import com.joysuch.wwyt.edu.repository.EduCertificateUserDao;
import com.joysuch.wwyt.monitoringcenter.bean.*;
import com.joysuch.wwyt.monitoringcenter.service.LocateServerService;
import com.joysuch.wwyt.util.Md5Util;
import com.joysuch.wwyt.util.PageableUtil;
import com.joysuch.wwyt.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.http.*;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author qingzhou
 * 2019-12-17
 */
@Slf4j
@Service
public class LocateServerServiceImpl implements LocateServerService {

    @Resource
    private BaseConfigService baseConfigService;
    @Autowired
    private BaseUserDao baseUserDao;
    @Autowired
    private BpWorkTypeDao bpWorkTypeDao;
    @Autowired
    private BpContractorStaffDao staffDao;
    @Autowired
    private BpDepartDao departDao;
    @Autowired
    private BpEnterpriseInfoDao bpEnterpriseInfoDao;
    @Autowired
    private BaseTypeGroupItemDao typeGroupItemDao;
    @Autowired
    private BpContractorDao bpContractorDao;
    @Autowired
    private BpJobDao jobDao;
    @Autowired
    private BpDepartDao bpDepartDao;
    @Autowired
    private BaseImageSyncService baseImageSyncService;
    @Autowired
    private BaseImageRespositoryDao baseImageRespositoryDao;
    @Autowired
    private BaseLoginAccountDao baseLoginAccountDao;
    @Autowired
    private EduCertificateUserDao eduCertificateUserDao;
    @Autowired
    private ApiBaseConfigMapper apiBaseConfigMapper;
    @Autowired
    private ApiBpWorkTypeMapper workTypeMapper;
    @Autowired
    private ApiBpDepartMapper departMapper;
    @Autowired
    private ApiBaseConfigMapper configMapper;
    @Autowired
    private ApiBaseUserMapper baseUserMapper;
    @Autowired
    private ApiBpEnterpriseInfoMapper infoMapper;
    @Autowired
    private ApiBpJobMapper jobMapper;
    @Autowired
    private ApiBaseTypeGroupItemMapper typeGroupItemMapper;
    @Autowired
    private ApiBaseImageRepositoryMapper imageRepositoryMapper;

    @Value("${wwyt.image.upload.dir}")
    private String imageUploadDir;

    @Resource
    private RedisClient redisClient;
    private static final ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(10, r -> {
        Thread thread = new Thread(r, "locate data worker");
        thread.setDaemon(true);
        return thread;
    });

    private RestTemplate restTemplate;

    private RestTemplate batchRestTemplate;

    public LocateServerServiceImpl() {
        SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
        requestFactory.setConnectTimeout(1000 * 15);// 设置超时
        requestFactory.setReadTimeout(1000 * 15);
        this.restTemplate = new RestTemplate(requestFactory);
        List<HttpMessageConverter<?>> converters = this.restTemplate.getMessageConverters();
        for (HttpMessageConverter<?> converter : converters) {
            if (converter instanceof MappingJackson2HttpMessageConverter) {
                List<MediaType> mediaTypeList = new ArrayList<>(converter.getSupportedMediaTypes());
                mediaTypeList.add(MediaType.APPLICATION_OCTET_STREAM);
                ((MappingJackson2HttpMessageConverter) converter).setSupportedMediaTypes(mediaTypeList);
            }
        }

        SimpleClientHttpRequestFactory batchRequestFactory = new SimpleClientHttpRequestFactory();
        batchRequestFactory.setConnectTimeout(1000 * 90);// 设置超时
        batchRequestFactory.setReadTimeout(1000 * 90);
        this.batchRestTemplate = new RestTemplate(batchRequestFactory);
        List<HttpMessageConverter<?>> batchConverters = this.batchRestTemplate.getMessageConverters();
        for (HttpMessageConverter<?> converter : batchConverters) {
            if (converter instanceof MappingJackson2HttpMessageConverter) {
                List<MediaType> mediaTypeList = new ArrayList<>(converter.getSupportedMediaTypes());
                mediaTypeList.add(MediaType.APPLICATION_OCTET_STREAM);
                ((MappingJackson2HttpMessageConverter) converter).setSupportedMediaTypes(mediaTypeList);
            }
        }

    }

    @Override
    public List<McAlarmMessageBean> alarmMessages() {
        try {
            LocateServerAlarmResult result = getLocateServerAlarmResult();
            if (result.getErrorCode() != null && result.getErrorCode() == 0) {
                return convert(result);
            }
        } catch (Exception e) {
            log.error("query locate server alarm message exception", e);
        }
        return Lists.newArrayList();
    }

    public String getLoginTokenDetail(Long tenentId, String orgCode) {
        BaseConfig ipConfig = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_SERVER_URL);
        if (terminateFun(ipConfig)) {
            log.info("ipConfig == null");
            return null;
        }
        BaseConfig appIdConfig = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_APP_ID);
        BaseConfig secretConfig = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_SERVER_SECRET);
        BaseConfig buildIdConfig = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_CURRENT_BUILD_ID);
        if (terminateFun(appIdConfig, secretConfig, buildIdConfig)) {
            log.info("appIdConfig or secretConfig or buildIdConfig == null");
            return null;
        }

        String loginAppId = appIdConfig.getValue();
        String loginSecret = secretConfig.getValue();
        String buildId = getBuildIds(buildIdConfig.getValue());
        HttpHeaders headers = new HttpHeaders();
        LocateLoginBean bean = new LocateLoginBean();
        String version = getLocateVersion();
        BaseConfig loginConfig;
        if ("4.x".equals(version)) {
            loginConfig = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_SERVER_V2_LOGIN_URL);
            bean.setAppId(loginAppId);
        } else {
            loginConfig = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_SERVER_LOGIN_URL);
            bean.setAppid(loginAppId);
        }
        if (terminateFun(loginConfig)) {
            log.info("loginConfig == null");
            return null;
        }
        String loginUrl = getHttpIpPort(ipConfig.getValue(), tenentId, orgCode) + loginConfig.getValue();
        List<String> buildIdList = JSON.parseArray(buildId, String.class);
        bean.setBuildIdList(buildIdList);
        headers.setContentType(MediaType.APPLICATION_JSON);
        String authorization = Md5Util.spring2Md5(loginAppId + loginSecret);
        headers.set("Authorization", authorization);
        HttpEntity httpEntity = new HttpEntity(bean, headers);
        ResponseEntity<LocateLoginRespDto> response = restTemplate.postForEntity(loginUrl, httpEntity, LocateLoginRespDto.class);
        LocateLoginRespDto<String> dto = response.getBody();
        if (response.getStatusCode() != null && response.getStatusCode() == HttpStatus.OK) {
            return dto.getData();
        }
        log.error("人员在岗在位登录接口调用错误,loginUrl:{},Authorization:{},data:{},errMsg:{}", loginUrl,
                authorization, bean, dto.getErrMsg());
        return null;
    }

    public String getApiLoginTokenDetail(Long tenentId, String orgCode) {
        ApiBaseConfigBean ipConfig = configMapper.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_SERVER_URL);
        if (apiTerminateFun(ipConfig)) {
            log.info("ipConfig == null");
            return null;
        }
        ApiBaseConfigBean appIdConfig = configMapper.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_APP_ID);
        ApiBaseConfigBean secretConfig = configMapper.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_SERVER_SECRET);
        ApiBaseConfigBean buildIdConfig = configMapper.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_CURRENT_BUILD_ID);
        if (apiTerminateFun(appIdConfig, secretConfig, buildIdConfig)) {
            log.info("appIdConfig or secretConfig or buildIdConfig == null");
            return null;
        }

        String loginAppId = appIdConfig.getValue();
        String loginSecret = secretConfig.getValue();
        String buildId = getBuildIds(buildIdConfig.getValue());
        HttpHeaders headers = new HttpHeaders();
        LocateLoginBean bean = new LocateLoginBean();
        ApiBaseConfigBean versionConfig = configMapper.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_VERSION);
        String version = "3.x";
        if (versionConfig != null) {
            version = versionConfig.getValue();
        }
        ApiBaseConfigBean loginConfig;
        if ("4.x".equals(version)) {
            loginConfig = configMapper.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_SERVER_V2_LOGIN_URL);
            bean.setAppId(loginAppId);
        } else {
            loginConfig = configMapper.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_SERVER_LOGIN_URL);
            bean.setAppid(loginAppId);
        }
        if (apiTerminateFun(loginConfig)) {
            log.info("loginConfig == null");
            return null;
        }
        String loginUrl = getApiHttpIpPort(ipConfig.getValue(), tenentId, orgCode) + loginConfig.getValue();
        List<String> buildIdList = JSON.parseArray(buildId, String.class);
        bean.setBuildIdList(buildIdList);
        headers.setContentType(MediaType.APPLICATION_JSON);
        String authorization = Md5Util.spring2Md5(loginAppId + loginSecret);
        headers.set("Authorization", authorization);
        HttpEntity httpEntity = new HttpEntity(bean, headers);
        ResponseEntity<LocateLoginRespDto> response = restTemplate.postForEntity(loginUrl, httpEntity, LocateLoginRespDto.class);
        LocateLoginRespDto<String> dto = response.getBody();
        if (response.getStatusCode() != null && response.getStatusCode() == HttpStatus.OK) {
            return dto.getData();
        }
        log.error("人员在岗在位登录接口调用错误,loginUrl:{},Authorization:{},data:{},errMsg:{}", loginUrl,
                authorization, bean, dto.getErrMsg());
        return null;
    }

    public String getLoginTokenDetailCross(Long tenentId, String orgCode, String buildId) {
        ApiBaseConfigBean ipConfigDto = apiBaseConfigMapper.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_SERVER_URL);
        BaseConfig ipConfig = new BaseConfig();
        BeanUtils.copyProperties(ipConfigDto, ipConfig);
        if (terminateFun(ipConfig)) {
            log.info("ipConfig == null");
            return null;
        }
        ApiBaseConfigBean appIdConfigDto = apiBaseConfigMapper.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_APP_ID);
        ApiBaseConfigBean secretConfigDto = apiBaseConfigMapper.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_SERVER_SECRET);
        BaseConfig appIdConfig = new BaseConfig();
        BaseConfig secretConfig = new BaseConfig();
        BeanUtils.copyProperties(appIdConfigDto, appIdConfig);
        BeanUtils.copyProperties(secretConfigDto, secretConfig);
//        BaseConfig buildIdConfig = baseConfigService.findFirstConfig();
        if (terminateFun(appIdConfig, secretConfig)) {
            log.info("appIdConfig or secretConfig or buildIdConfig == null");
            return null;
        }

        String loginAppId = appIdConfig.getValue();
        String loginSecret = secretConfig.getValue();
//        String buildId = getBuildIds(buildIdConfig.getValue());
        HttpHeaders headers = new HttpHeaders();
        LocateLoginBean bean = new LocateLoginBean();
        String version = getLocateVersion();
        BaseConfig loginConfig = new BaseConfig();
        if ("4.x".equals(version)) {
            ApiBaseConfigBean loginConfigDto = apiBaseConfigMapper.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_SERVER_V2_LOGIN_URL);
            BeanUtils.copyProperties(loginConfigDto, loginConfig);
            bean.setAppId(loginAppId);
        } else {
            ApiBaseConfigBean loginConfigDto = apiBaseConfigMapper.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_SERVER_LOGIN_URL);
            BeanUtils.copyProperties(loginConfigDto, loginConfig);
            bean.setAppid(loginAppId);
        }
        if (terminateFun(loginConfig)) {
            log.info("loginConfig == null");
            return null;
        }
        String loginUrl = getHttpIpPort(ipConfig.getValue()) + loginConfig.getValue();
        ArrayList<String> strings = Lists.newArrayList(buildId);
        String s = JSON.toJSONString(strings);
        List<String> buildIdList = JSON.parseArray(s, String.class);
        bean.setBuildIdList(buildIdList);
        headers.setContentType(MediaType.APPLICATION_JSON);
        String authorization = Md5Util.spring2Md5(loginAppId + loginSecret);
        headers.set("Authorization", authorization);
        HttpEntity httpEntity = new HttpEntity(bean, headers);
        ResponseEntity<LocateLoginRespDto> response = restTemplate.postForEntity(loginUrl, httpEntity, LocateLoginRespDto.class);
        LocateLoginRespDto<String> dto = response.getBody();
        if (response.getStatusCode() != null && response.getStatusCode() == HttpStatus.OK) {
            return dto.getData();
        }
        log.error("人员在岗在位登录接口调用错误,loginUrl:{},Authorization:{},data:{},errMsg:{}", loginUrl,
                authorization, bean, dto.getErrMsg());
        return null;
    }

    /**
     * 获取人员在岗在位版本
     */
    @Override
    public String getLocateVersion() {
        BaseConfig versionConfig = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_VERSION);
        String version = "3.x";
        if (versionConfig != null) {
            version = versionConfig.getValue();
        }
        return version;
    }

    @Override
    public String getApiLocateVersion(BuildDataDto dto) {
        ApiBaseConfigBean versionConfig = configMapper.findConfig(dto.getTenentId(), dto.getOrgCode(), BaseConfigCodes.LOCATE_VERSION);
        String version = "3.x";
        if (versionConfig != null) {
            version = versionConfig.getValue();
        }
        return version;
    }

    @Override
    public String getLocateVersion(Long tenentId, String orgCode) {
        BaseConfig versionConfig = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_VERSION);
        String version = "3.x";
        if (versionConfig != null) {
            version = versionConfig.getValue();
        }
        return version;
    }

    private String getBuildIds(String locateCurrentBuildId) {
        ArrayList<String> strings = Lists.newArrayList(locateCurrentBuildId);
        return JSON.toJSONString(strings);
    }

    @Override
    public ResultBean getLocateAlarm(LocateAlarmBean bean) {
        if (baseConfigService.checkIfSync()) {
            return ResultBean.defaultSuccessResult();
        }
        Pageable pageable = PageRequest.of(bean.getPageNumber(), bean.getPageSize());
        String loginToken = null;
        if (bean.getFlag()) {
            loginToken = getLoginToken();
            if (loginToken == null) {
                return ResultBean.defaultSuccessResult();
                //return ResultBean.fail(101, "人员在岗在位接口调用错误，请稍后重试");
            }
        }
        BaseConfig ipConfig = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_SERVER_URL);
        BaseConfig alarmUrlConfig = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_SERVER_ALARM_LIST);
        if (ipConfig == null || alarmUrlConfig == null) {
            return ResultBean.defaultSuccessResult();
        }
        String alarmUrl = getHttpIpPort(ipConfig.getValue()) + alarmUrlConfig.getValue();
        ResponseEntity<LocateLoginRespDto> response = rest(bean, loginToken, alarmUrl, LocateLoginRespDto.class);
        LocateLoginRespDto dto = response.getBody();
        if (response.getStatusCode() != null && response.getStatusCode() == HttpStatus.OK) {
            List<LinkedHashMap> records = (List<LinkedHashMap>) dto.getData();
            if (CollectionUtils.isEmpty(records)) {
                return ResultBean.defaultSuccessResult();
            }
            if (bean.getAlarmState() == null) {
                List<LinkedHashMap> list = PageableUtil.getList(pageable, records);
                List<LocateAlarmRecord> convert = convert(list);
                return ResultBean.pageData(convert, records.size());
            } else {
                List<LocateAlarmRecord> convert = convert(records);
                List<LocateAlarmRecord> result = filter(convert, bean.getAlarmState());
                List<LocateAlarmRecord> list = PageableUtil.getList(pageable, result);
                return ResultBean.pageData(list, result.size());
            }
        }
        log.error("人员在岗在位调用报警列表接口错误，alarmUrl:{},data:{},errMsg:{}", alarmUrl, bean, dto.getErrMsg());
        return ResultBean.defaultSuccessResult();
    }

    private List<LocateAlarmRecord> filter(List<LocateAlarmRecord> convert, Integer alarmState) {
        return convert.stream().filter(r -> {
            if (alarmState == 1 && r.getHandleTime() == null) {
                return true;
            } else if (alarmState == 0 && r.getHandleTime() != null) {
                return true;
            }
            return false;
        }).collect(Collectors.toList());
    }

    /**
     * 获取人员在岗在位区域正在报警总数
     */
    @Override
    public int getLocateAlarmCount(String buildId) {
        LocateAlarmBean bean = new LocateAlarmBean();
        bean.setBuildId(buildId);
        String loginToken = getLoginToken();
        if (loginToken == null) {
            log.error("人员在岗在位登录接口调用失败,bean:{}", bean);
            return 0;
        }
        BaseConfig ipConfig = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_SERVER_URL);
        BaseConfig alarmListConfig = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_SERVER_ALARM_LIST);
        if (ipConfig == null || alarmListConfig == null) {
            return 0;
        }
        String alarmUrl = getHttpIpPort(ipConfig.getValue()) + alarmListConfig.getValue();
        ResponseEntity<LocateLoginRespDto> response = rest(bean, loginToken, alarmUrl, LocateLoginRespDto.class);
        LocateLoginRespDto dto = response.getBody();
        if (response.getStatusCode() != null && response.getStatusCode() == HttpStatus.OK) {
            List<LinkedHashMap> records = (List<LinkedHashMap>) dto.getData();
            Long total = (records == null || records.size() == 0) ? 0 : getTotalAlarming(records);
            return total.intValue();
        }
        log.error("人员在岗在位调用报警列表接口错误，alarmUrl:{},data:{},errMsg:{}", alarmUrl, bean, dto.getErrMsg());
        return 0;
    }

    private long getTotalAlarming(List<LinkedHashMap> data) {
        return data.stream().filter(r -> r.get("handleTime") == null).count();
    }

    @Override
    public ResultBean areaAlarmBatch(LocateAlarmBatchBean bean) {
        if (baseConfigService.checkIfSync()) {
            return ResultBean.fail(Status.LOCATE_VERSION_ERROE);
        }
        String loginToken = getLoginToken();
        if (loginToken == null) {
            return ResultBean.fail(101, "人员在岗在位接口调用错误，请稍后重试");
        }
        BaseConfig ipConfig = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_SERVER_URL);
        BaseConfig alarmBatchConfig = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_SERVER_ALARM_BATCH);
        if (ipConfig == null || alarmBatchConfig == null) {
            return ResultBean.fail(101, "请正确配置人员在岗在位地址参数");
        }
        String alarmBatchUrl = getHttpIpPort(ipConfig.getValue()) + alarmBatchConfig.getValue();
        ResponseEntity<LocateLoginRespDto> response = rest(bean, loginToken, alarmBatchUrl, LocateLoginRespDto.class);
        LocateLoginRespDto dto = response.getBody();
        if (response.getStatusCode() != null && response.getStatusCode() == HttpStatus.OK) {
            return ResultBean.defaultSuccessResult();
        }
        log.error("人员在岗在位调用报警批量处理接口错误，alarmBatchUrl:{},data:{},errMsg:{}", alarmBatchUrl, bean, dto.getErrMsg());
        return ResultBean.fail(101, dto.getErrMsg());
    }

    /**
     * 同步人员
     * 4.x及以上版本
     * 1.如果人员在岗在位先创建了人员，则会通过数据库导入人员的方式同步过来
     * 2.查询所有存在的uniqueId, 存在则修改，不存在则新增
     * 3.无uniqueId的数据不同步；如果存在说明化工数据没写入五位一体数据库
     * 4.每次只同步状态为“未同步”的数据(只适用同步所有数据的情况)
     * 5.单体数据同步失败时，即使此数据之前已同步成功也要改为“未同步”
     * 6.新增时如果没有sn号，不新增
     * 7.修改时如果没有sn号，调解绑接口；因为他们接口sn号必填
     */
    public void syncLocateUsersV2(List<BaseUser> list) {
        //过滤无uniqueId的数据
        list = list.stream().filter(r -> r.getUniqueId() != null).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        log.info("开始批量同步人员v2...");
        for (BaseUser baseUser : list) {
            syncLocateUsersV2(baseUser, 1);
        }
        log.info("结束批量同步人员v2...");
    }

    //flag 0 web端的单体修改/新增; 1 批量处理下的单体操作
    public void syncLocateUsersV2(BaseUser user, Integer flag) {
        if (user == null || user.getUniqueId() == null) {
            return;
        }
        log.info("开始同步人员...");
        if (flag == 1 && user.isLocateSync()) {
            return;
        }
        String loginToken = getLoginToken();
        if (loginToken == null) {
            log.error("同步人员v2,loginToken为空,检查系统配置和网络...");
            return;
        }
        String buildId = getBuildId();
        if (buildId == null) return;
        BaseConfig deleteConfig = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_SERVER_V2_EMPLOYEE_DELETE);
        if (deleteConfig == null) return;
        String deleteUrl = getIpPortUrl(deleteConfig.getValue());

        //判断是否是删除的数据  删除人员，他们会自动解绑标签
        if (DataStateTypes.DELETE.getState().equals(user.getState())) {
            LocateUserBean<String> bean = new LocateUserBean<>(buildId, Lists.newArrayList(user.getUniqueId()));
            ResponseEntity<LocateLoginRespDto> response = null;
            try {
                response = rest(bean, loginToken, deleteUrl, LocateLoginRespDto.class);
            } catch (Exception e) {
                log.error("同步人员v2删除失败 e{}", e);
            }
            if (response != null && response.getStatusCode() != null && response.getStatusCode().value() == HttpStatus.OK.value()) {
                LocateLoginRespDto body = response.getBody();
                if (body != null && body.getCode() == 0) {
                    log.info("同步人员v2，删除success，userId:{},errorBody:{}", user.getId(), response);
                    user.setLocateSync(true);
                } else {
                    log.error("同步人员v2，删除fail，userId:{},errorBody:{}", user.getId(), response);
                    user.setLocateSync(false);
                }
            } else {
                log.info("同步人员v2，删除fail，userId:{},response:{}", user.getId(), JSON.toJSONString(response));
                user.setLocateSync(false);
            }
            baseUserDao.save(user);
            return;
        }

        byte failFlag = 1;
        //同步人员信息 返回保存失败的人员集合
        List<SyncBatchDataReturnBean> returnBeans = this.syncSaveUser(Lists.newArrayList(user), buildId, loginToken);
        if (CollectionUtils.isEmpty(returnBeans)) {
            failFlag = 0;
        }
        //同步人员头像
        if (failFlag == 0) {
            failFlag = baseImageSyncService.syncPeopleHeadImage(user.getIdCardImgId(), user.getUniqueId(), buildId, loginToken, failFlag);
        }
        //调用接口失败
        if (failFlag == 1) {
            user.setLocateSync(false);
            baseUserDao.save(user);
            log.info("同步人员v3, 同步失败, userId:" + user.getId());
        } else {
            user.setLocateSync(true);
            baseUserDao.save(user);
            log.info("同步人员v3, 同步成功, userId:" + user.getId());
        }
    }

    //flag 0 web端的单体修改/新增; 1 批量处理下的单体操作
    public void apiSyncLocateUsersV2(BaseUser user, Integer flag, BuildDataDto dto) {
        if (user == null || user.getUniqueId() == null) {
            return;
        }
        log.info("开始同步人员...");
        if (flag == 1 && user.isLocateSync()) {
            return;
        }
        String loginToken = getApiLoginToken(dto);
        if (loginToken == null) {
            log.error("同步人员v2,loginToken为空,检查系统配置和网络...");
            return;
        }
        String buildId = getBuildId();
        if (buildId == null) return;
        ApiBaseConfigBean deleteConfig = configMapper.findConfig(dto.getTenentId(), dto.getOrgCode(), BaseConfigCodes.LOCATE_SERVER_V2_EMPLOYEE_DELETE);
        if (deleteConfig == null) return;
        String deleteUrl = getApiIpPortUrl(deleteConfig.getValue(), dto);

        //判断是否是删除的数据  删除人员，他们会自动解绑标签
        if (DataStateTypes.DELETE.getState().equals(user.getState())) {
            LocateUserBean<String> bean = new LocateUserBean<>(buildId, Lists.newArrayList(user.getUniqueId()));
            ResponseEntity<LocateLoginRespDto> response = null;
            try {
                response = rest(bean, loginToken, deleteUrl, LocateLoginRespDto.class);
            } catch (Exception e) {
                log.error("同步人员v2删除失败 e{}", e);
            }
            if (response != null && response.getStatusCode() != null && response.getStatusCode().value() == HttpStatus.OK.value()) {
                LocateLoginRespDto body = response.getBody();
                if (body != null && body.getCode() == 0) {
                    log.info("同步人员v2，删除success，userId:{},errorBody:{}", user.getId(), response);
                    user.setLocateSync(true);
                } else {
                    log.error("同步人员v2，删除fail，userId:{},errorBody:{}", user.getId(), response);
                    user.setLocateSync(false);
                }
            } else {
                log.info("同步人员v2，删除fail，userId:{},response:{}", user.getId(), JSON.toJSONString(response));
                user.setLocateSync(false);
            }
            ApiBaseUserBean userBean = new ApiBaseUserBean();
            BeanUtils.copyProperties(user, userBean);
            baseUserMapper.updateById(userBean);
//            baseUserDao.save(user);
            return;
        }

        byte failFlag = 1;
        //同步人员信息 返回保存失败的人员集合
        List<SyncBatchDataReturnBean> returnBeans = this.apiSyncSaveUser(Lists.newArrayList(user), buildId, loginToken, dto);
        if (CollectionUtils.isEmpty(returnBeans)) {
            failFlag = 0;
        }
        //同步人员头像
        if (failFlag == 0) {
            failFlag = baseImageSyncService.apiSyncPeopleHeadImage(user.getIdCardImgId(), user.getUniqueId(), buildId, loginToken, failFlag, dto);
        }
        //调用接口失败
        if (failFlag == 1) {
            user.setLocateSync(false);
            ApiBaseUserBean userBean = new ApiBaseUserBean();
            BeanUtils.copyProperties(user, userBean);
            baseUserMapper.updateById(userBean);
            log.info("同步人员v3, 同步失败, userId:" + user.getId());
        } else {
            user.setLocateSync(true);
            ApiBaseUserBean userBean = new ApiBaseUserBean();
            BeanUtils.copyProperties(user, userBean);
            baseUserMapper.updateById(userBean);
            log.info("同步人员v3, 同步成功, userId:" + user.getId());
        }
    }


    /**
     * 同步人员信息
     *
     * @param users
     * @param buildId
     * @param loginToken
     * @return
     */
    @Override
    public List<SyncBatchDataReturnBean> syncSaveUser(List<BaseUser> users, String buildId, String loginToken) {
        List<SyncBatchDataReturnBean> list = new ArrayList<>();
        List<LocateUserDetailBeanV2> userDetailBeanV2 = getUserDetailBeanV2(users);
        LocateUserBean<LocateUserDetailBeanV2> userBean = new LocateUserBean<>(buildId, userDetailBeanV2);
        BaseConfig addConfig = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_SERVER_V3_EMPLOYEE_SAVE);
        if (addConfig == null) {
            return list;
        }
        String addUrl = getIpPortUrl(addConfig.getValue());
        log.info("人员同步参数==========" + userDetailBeanV2);
        ResponseEntity<LocateLoginRespDto> addResponse = null;
        try {
            addResponse = batchRest(userBean, loginToken, addUrl, LocateLoginRespDto.class);
        } catch (Exception e) {
            log.error("同步人员v3 e{}", e);
        }
        if (addResponse != null && addResponse.getStatusCode() != null && addResponse.getStatusCode().value() == HttpStatus.OK.value() && addResponse.getBody() != null) {
            LocateLoginRespDto body = addResponse.getBody();
            if (StringUtils.isNotBlank(body.getErrMsg()) || (body.getData() != null && !CollectionUtils.isEmpty((List<SyncBatchDataReturnBean>) body.getData()))) {
                log.error("同步人员v3, 保存失败, users:" + users + " msg:" + body.getMsg() + " data:" + body.getData());
                if (body.getCode() != null && (body.getCode().equals(500) || body.getCode().equals(400) || body.getCode().equals(-90))) {
                    for (BaseUser user : users) {
                        SyncBatchDataReturnBean rb = new SyncBatchDataReturnBean();
                        rb.setUniqueId(user.getUniqueId());
                        rb.setMsg(body.getMsg() + "--" + body.getDetailMessage());
                        list.add(rb);
                    }
                }
                List<SyncBatchDataReturnBean> data = (List<SyncBatchDataReturnBean>) body.getData();
                if (!CollectionUtils.isEmpty(data)) {
                    String str = JSON.toJSONString(data);
                    list = JSONObject.parseArray(str, SyncBatchDataReturnBean.class);
                    log.error("returnData: " + list);
                }
            } else {
                if (body.getCode() == 0) {
                    log.info("同步人员v3, 保存成功, users:" + users);
                } else {
                    log.error("同步人员v3, 保存接口报错, users:{}，errorBody:{}", users, body);
                }
            }
        } else {
            log.error("同步人员v3, 保存接口报错, users count={}，addResponse:{}", users.size(), JSON.toJSONString(addResponse));
        }
        return list;
    }

    @Override
    public List<SyncBatchDataReturnBean> apiSyncSaveUser(List<BaseUser> users, String buildId, String loginToken, BuildDataDto dto) {
        List<SyncBatchDataReturnBean> list = new ArrayList<>();
        List<LocateUserDetailBeanV2> userDetailBeanV2 = getApiUserDetailBeanV2(users);
        LocateUserBean<LocateUserDetailBeanV2> userBean = new LocateUserBean<>(buildId, userDetailBeanV2);
        ApiBaseConfigBean addConfig = configMapper.findConfig(dto.getTenentId(), dto.getOrgCode(), BaseConfigCodes.LOCATE_SERVER_V3_EMPLOYEE_SAVE);
        if (addConfig == null) {
            return list;
        }
        String addUrl = getApiIpPortUrl(addConfig.getValue(), dto);
        log.info("人员同步参数==========" + userDetailBeanV2);
        ResponseEntity<LocateLoginRespDto> addResponse = null;
        try {
            addResponse = batchRest(userBean, loginToken, addUrl, LocateLoginRespDto.class);
        } catch (Exception e) {
            log.error("同步人员v3 e{}", e);
        }
        if (addResponse != null && addResponse.getStatusCode() != null && addResponse.getStatusCode().value() == HttpStatus.OK.value() && addResponse.getBody() != null) {
            LocateLoginRespDto body = addResponse.getBody();
            if (StringUtils.isNotBlank(body.getErrMsg()) || (body.getData() != null && !CollectionUtils.isEmpty((List<SyncBatchDataReturnBean>) body.getData()))) {
                log.error("同步人员v3, 保存失败, users:" + users + " msg:" + body.getMsg() + " data:" + body.getData());
                if (body.getCode() != null && (body.getCode().equals(500) || body.getCode().equals(400) || body.getCode().equals(-90))) {
                    for (BaseUser user : users) {
                        SyncBatchDataReturnBean rb = new SyncBatchDataReturnBean();
                        rb.setUniqueId(user.getUniqueId());
                        rb.setMsg(body.getMsg() + "--" + body.getDetailMessage());
                        list.add(rb);
                    }
                }
                List<SyncBatchDataReturnBean> data = (List<SyncBatchDataReturnBean>) body.getData();
                if (!CollectionUtils.isEmpty(data)) {
                    String str = JSON.toJSONString(data);
                    list = JSONObject.parseArray(str, SyncBatchDataReturnBean.class);
                    log.error("returnData: " + list);
                }
            } else {
                if (body.getCode() == 0) {
                    log.info("同步人员v3, 保存成功, users:" + users);
                } else {
                    log.error("同步人员v3, 保存接口报错, users:{}，errorBody:{}", users, body);
                }
            }
        } else {
            log.error("同步人员v3, 保存接口报错, users count:{}，addResponse:{}", users.size(), JSON.toJSONString(addResponse));
        }
        return list;
    }

    private List<LocateUserDetailBeanV2> getUserDetailBeanV2(List<BaseUser> users) {
        List<LocateUserDetailBeanV2> list = new ArrayList<>();
        for (BaseUser user : users) {
            LocateUserDetailBeanV2 bean = new LocateUserDetailBeanV2();
            BeanUtils.copyProperties(user, bean);
            //邮编不能传空串
            bean.setPostcode("".equals(user.getPostcode()) ? null : user.getPostcode());
            //证件类型
            bean.setIdCardType(user.getIdCardType() == null ? null : BaseIdCardTypes.getIdName(new Integer(user.getIdCardType().intValue())));

            //工作单位
            Long workCompanyId = user.getWorkCompanyId();
            if (workCompanyId != null) {
                bpEnterpriseInfoDao.findById(workCompanyId).ifPresent(r -> bean.setWorkCompany(r.getName()));
            }
            //部门uniqueId todo
            //bean.setDepartId(1341651481497178112L);
            Long departId = user.getDepartId();
            if (departId != null) {
                departDao.findById(departId).ifPresent(r -> bean.setDepartId(r.getUniqueId()));
            }
            //岗位uniqueId todo
            Long job = user.getJob();
            if (job != null) {
                jobDao.findById(job).ifPresent(r -> bean.setJob(r.getUniqueId()));
            }
            //人员在岗在位逻辑：没有人员报警模板，就取岗位下的模板，如果没有就报错
            //bean.setJob(1341651481589452801L);
            //民族
            Long nation = user.getNation();
            if (nation != null && nation != 0) {
                typeGroupItemDao.findById(nation).ifPresent(r -> bean.setNationName(r.getName()));
            }
            //参加工作时间
            Date joinWorkDate = user.getJoinWorkDate();
            if (joinWorkDate != null) {
                LocalDate localDate = DateTimeUtil.date2LocalDateTime(joinWorkDate).toLocalDate();
                bean.setJoinWorkDate(localDate.toString());
            }
            //人员详情链接
            bean.setUrl(user.getRefUrl());
            //健康状态
            Long healthStatus = user.getHealthStatus();
            if (healthStatus != null && healthStatus != 0) {
                typeGroupItemDao.findById(healthStatus).ifPresent(r -> bean.setHealthStatusName(r.getName()));
            }
            //学历
            Long education = user.getEducation();
            if (education != null && education != 0) {
                typeGroupItemDao.findById(education).ifPresent(r -> bean.setEducationName(r.getName()));
            }
            //人员模板
            Long alarmTemplateId = user.getAlarmTemplateId();
            if (alarmTemplateId != null) {
                bean.setPersonTemplateId(alarmTemplateId.intValue());
            } else {
                bean.setPersonTemplateId(null);
            }
            bean.setCardNumber(user.getCardNumber());
            //帽子id
            if (user.getCapId() != null) {
                Optional<BaseImageRepository> br = baseImageRespositoryDao.findById(user.getCapId());
                if (br.isPresent() && br.get().isLocateSync()) {
                    bean.setIconId(br.get().getUniqueId());
                }
            }
            list.add(bean);
        }
        return list;
    }

    private List<LocateUserDetailBeanV2> getApiUserDetailBeanV2(List<BaseUser> users) {
        List<LocateUserDetailBeanV2> list = new ArrayList<>();
        for (BaseUser user : users) {
            LocateUserDetailBeanV2 bean = new LocateUserDetailBeanV2();
            BeanUtils.copyProperties(user, bean);
            //邮编不能传空串
            bean.setPostcode("".equals(user.getPostcode()) ? null : user.getPostcode());
            //证件类型
            bean.setIdCardType(user.getIdCardType() == null ? null : BaseIdCardTypes.getIdName(new Integer(user.getIdCardType().intValue())));

            //工作单位
            Long workCompanyId = user.getWorkCompanyId();
            if (workCompanyId != null) {
                ApiBpEnterpriseInfoBean infoBean = infoMapper.selectById(workCompanyId);
                if (infoBean != null) {
                    bean.setWorkCompany(infoBean.getName());
                }
            }
            //部门uniqueId todo
            //bean.setDepartId(1341651481497178112L);
            Long departId = user.getDepartId();
            if (departId != null) {
                ApiBpDepartBean departBean = departMapper.selectById(departId);
                if (departBean != null) {
                    bean.setDepartId(departBean.getUniqueId());
                }
            }
            //岗位uniqueId todo
            Long job = user.getJob();
            if (job != null) {
                ApiBpJobBean jobBean = jobMapper.selectById(job);
                if (jobBean != null) {
                    bean.setJob(jobBean.getUniqueId());
                }
//                    jobDao.findById(job).ifPresent(r -> bean.setJob(r.getUniqueId()));
            }
            //人员在岗在位逻辑：没有人员报警模板，就取岗位下的模板，如果没有就报错
            //bean.setJob(1341651481589452801L);
            //民族
            Long nation = user.getNation();
            if (nation != null && nation != 0) {
                ApiBaseTypeGroupItemBean apiBaseTypeGroupItemBean = typeGroupItemMapper.selectById(nation);
                if (apiBaseTypeGroupItemBean != null) {
                    bean.setNationName(apiBaseTypeGroupItemBean.getName());
                }
//                typeGroupItemDao.findById(nation).ifPresent(r -> bean.setNationName(r.getName()));
            }
            //参加工作时间
            Date joinWorkDate = user.getJoinWorkDate();
            if (joinWorkDate != null) {
                LocalDate localDate = DateTimeUtil.date2LocalDateTime(joinWorkDate).toLocalDate();
                bean.setJoinWorkDate(localDate.toString());
            }
            //人员详情链接
            bean.setUrl(user.getRefUrl());
            //健康状态
            Long healthStatus = user.getHealthStatus();
            if (healthStatus != null && healthStatus != 0) {
                ApiBaseTypeGroupItemBean apiBaseTypeGroupItemBean = typeGroupItemMapper.selectById(nation);
                if (apiBaseTypeGroupItemBean != null) {
                    bean.setHealthStatusName(apiBaseTypeGroupItemBean.getName());
                }
//                typeGroupItemDao.findById(healthStatus).ifPresent(r -> bean.setHealthStatusName(r.getName()));
            }
            //学历
            Long education = user.getEducation();
            if (education != null && education != 0) {
                ApiBaseTypeGroupItemBean apiBaseTypeGroupItemBean = typeGroupItemMapper.selectById(nation);
                if (apiBaseTypeGroupItemBean != null) {
                    bean.setEducationName(apiBaseTypeGroupItemBean.getName());
                }
//                typeGroupItemDao.findById(education).ifPresent(r -> bean.setEducationName(r.getName()));
            }
            //人员模板
            Long alarmTemplateId = user.getAlarmTemplateId();
            if (alarmTemplateId != null) {
                bean.setPersonTemplateId(alarmTemplateId.intValue());
            } else {
                bean.setPersonTemplateId(null);
            }
            bean.setCardNumber(user.getCardNumber());
            //帽子id
            if (user.getCapId() != null) {
                ApiBaseImageRepositoryBean apiBaseImageRepositoryBean = imageRepositoryMapper.selectById(user.getCapId());
//                Optional<BaseImageRepository> br = baseImageRespositoryDao.findById(user.getCapId());
//                if (br.isPresent() && br.get().isLocateSync()) {
//                    bean.setIconId(br.get().getUniqueId());
//                }
                if (apiBaseImageRepositoryBean != null && apiBaseImageRepositoryBean.getLocateSync()) {
                    bean.setIconId(apiBaseImageRepositoryBean.getUniqueId());
                }
            }
            list.add(bean);
        }
        return list;
    }

    public void syncLocateStaffV2(List<BpContractorStaff> list) {
        //过滤无uniqueId的数据
        list = list.stream().filter(r -> r.getUniqueId() != null).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        log.info("开始批量同步承包商人员v2...");
        for (BpContractorStaff staff : list) {
            syncLocateStaffV2(staff, 1);
        }
        log.info("结束批量同步承包商人员v2...");
    }

    //flag 0 web端的单体修改/新增; 1 批量处理下的单体操作
    public void syncLocateStaffV2(BpContractorStaff staff, Integer flag) {
        if (staff == null || staff.getUniqueId() == null) {
            return;
        }
        log.info("开始同步承包商人员...");
        if (flag == 1 && staff.isLocateSync()) {
            return;
        }
        String loginToken = getLoginToken();
        if (loginToken == null) {
            log.error("同步承包商人员v2,loginToken为空,检查系统配置和网络...");
            return;
        }
        String buildId = getBuildId();
        BaseConfig deleteConfig = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_SERVER_V2_STAFF_DELETE);
        if (deleteConfig == null) return;
        String deleteUrl = getIpPortUrl(deleteConfig.getValue());

        //判断是否是删除的数据   删除人员，他们会自动解绑标签
        if (DataStateTypes.UN_EFFECTIVE.getState().equals(staff.getState())) {
            LocateStaffDeleteBean bean = new LocateStaffDeleteBean(buildId, Lists.newArrayList(staff.getUniqueId()), true);
            ResponseEntity<LocateLoginRespDto> response = null;
            try {
                response = rest(bean, loginToken, deleteUrl, LocateLoginRespDto.class);
            } catch (Exception e) {
                log.error("同步承包商人员v2,删除失败 e{}", e);
            }
            if (response != null && response.getStatusCode() != null && response.getStatusCode().value() == HttpStatus.OK.value() && response.getBody() != null) {
                LocateLoginRespDto body = response.getBody();
                if (body != null && body.getCode() == 0) {
                    log.info("同步承包商人员v2，删除success，staffId:{},errorBody:{}", staff.getId(), response);
                    staff.setLocateSync(true);
                } else {
                    staff.setLocateSync(false);
                    log.error("同步承包商人员v2，删除fail，staffId:{},errorBody:{}", staff.getId(), response);
                }
            } else {
                log.info("同步承包商人员v2，删除fail，staffId:{},response:{}", staff.getId(), JSON.toJSONString(response));
                staff.setLocateSync(false);
            }
            staffDao.save(staff);
            return;
        }

        byte failFlag = 1;
        List<SyncBatchDataReturnBean> returnBeans = this.syncSaveStaff(Lists.newArrayList(staff), buildId, loginToken);
        if (CollectionUtils.isEmpty(returnBeans)) {
            failFlag = 0;
        }
        if (failFlag == 0 && StringUtils.isNotBlank(staff.getIdCardImgJson())) {
            BaseAttachmentBean attachmentBean = JSONObject.parseObject(staff.getIdCardImgJson(), BaseAttachmentBean.class);
            baseImageSyncService.syncPeopleHeadImage(attachmentBean.getId(), staff.getUniqueId(), buildId, loginToken, failFlag);
        }
        //调用接口失败
        if (failFlag == 1) {
            staff.setLocateSync(false);
            staffDao.save(staff);
            log.info("同步承包商人员v2, 同步失败, staffId:" + staff.getId());
        } else {
            staff.setLocateSync(true);
            staffDao.save(staff);
            log.info("同步承包商人员v2, 同步成功, staffId:" + staff.getId());
        }
    }

    @Override
    public List<SyncBatchDataReturnBean> syncSaveStaff(List<BpContractorStaff> staffs, String buildId, String loginToken) {
        //准备人员detail数据
        List<SyncBatchDataReturnBean> list = new ArrayList<>();
        List<LocateStaffDetailBeanV2> staffDetailBeanV2 = getStaffDetailBeanV2(staffs);
        LocateUserBean<LocateStaffDetailBeanV2> userBean = new LocateUserBean<>(buildId, staffDetailBeanV2);
        BaseConfig config = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_SERVER_V3_STAFF_SAVE);
        if (config == null) {
            return list;
        }
        String url = getIpPortUrl(config.getValue());
        log.info("承包商人员同步参数===============" + staffDetailBeanV2);
        ResponseEntity<LocateLoginRespDto> response = null;
        try {
            response = batchRest(userBean, loginToken, url, LocateLoginRespDto.class);
        } catch (Exception e) {
            log.error("同步承包商人员v2 e{}", e);
        }
        if (response != null && response.getStatusCode() != null && response.getStatusCode().value() == HttpStatus.OK.value()) {
            LocateLoginRespDto body = response.getBody();
            if (StringUtils.isNotBlank(body.getErrMsg()) || (body.getData() != null && !CollectionUtils.isEmpty((List<SyncBatchDataReturnBean>) body.getData()))) {
                log.error("同步承包商人员v2, 保存失败, staffs:" + staffs + " msg: " + body.getMsg() + " data:" + body.getData());
                if (body.getCode() != null && (body.getCode().equals(500) || body.getCode().equals(400) || body.getCode().equals(-90))) {
                    for (BpContractorStaff staff : staffs) {
                        SyncBatchDataReturnBean rb = new SyncBatchDataReturnBean();
                        rb.setUniqueId(staff.getUniqueId());
                        rb.setMsg(body.getMsg() + "--" + body.getDetailMessage());
                        list.add(rb);
                    }
                }
                List<SyncBatchDataReturnBean> data = (List<SyncBatchDataReturnBean>) body.getData();
                if (!CollectionUtils.isEmpty(data)) {
                    String str = JSON.toJSONString(data);
                    list = JSONObject.parseArray(str, SyncBatchDataReturnBean.class);
                    log.error("returnData: " + list);
                }
            } else {
                if (body != null && body.getCode() == 0) {
                    log.info("同步承包商人员v2, 保存成功, staffs:" + staffs);
                } else {
                    log.error("同步承包商人员v2, 保存调用接口报错, staffs:{}，errorBody:{}", staffs, body);
                }
            }
        } else {
            log.error("同步承包商人员v2, 保存调用接口报错, staffs count={}，response:{}", staffs.size(), JSON.toJSONString(response));
        }
        return list;
    }

    @Override
    public String getV3ScreenToken() {
        String loginToken = getLoginToken();
        if (StringUtils.isBlank(loginToken)) {
            log.info("获取大屏token:loginToken is blank");
            return null;

        }
        String tokenUrl = getUrl("getV3ScreenToken", Context.getCurrentTenantId(), Context.getCompanyCode().substring(0, 7));
        if (StringUtils.isBlank(tokenUrl)) {
            log.info("获取大屏token:url is blank");
            return null;
        }
        BaseConfig appIdConfig = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_APP_ID);
        BaseConfig secretConfig = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_SERVER_SECRET);
        BaseConfig buildIdConfig = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_CURRENT_BUILD_ID);
        if (terminateFun(appIdConfig, secretConfig, buildIdConfig)) {
            log.info("获取大屏token:appIdConfig or secretConfig or buildIdConfig == null");
            return null;
        }
        String loginAppId = appIdConfig.getValue();
        String loginSecret = secretConfig.getValue();
        String buildId = getBuildId();
        if (StringUtils.isBlank(buildId)) {
            log.info("获取大屏token:buildId is blank");
            return null;
        }
        HttpHeaders headers = new HttpHeaders();
        LocateLoginBean bean = new LocateLoginBean();
        bean.setAppId(loginAppId);
        bean.setBuildId(buildId);
        headers.setContentType(MediaType.APPLICATION_JSON);
        String authorization = Md5Util.spring2Md5(loginAppId + loginSecret);
        headers.set("Authorization", authorization);
        headers.set("token", loginToken);
        HttpEntity httpEntity = new HttpEntity(bean, headers);
        ResponseEntity<LocateLoginRespDto> response = restTemplate.postForEntity(tokenUrl, httpEntity, LocateLoginRespDto.class);
        LocateLoginRespDto<String> dto = response.getBody();
        if (response.getStatusCode() != null && response.getStatusCode() == HttpStatus.OK) {
            return dto.getData();
        }
        log.error("人员在岗在位获取大屏token调用错误,url:{},Authorization:{},data:{},errMsg:{}", tokenUrl,
                authorization, bean, dto.getErrMsg());
        return null;
    }


    private List<LocateStaffDetailBeanV2> getStaffDetailBeanV2(List<BpContractorStaff> staffs) {
        List<LocateStaffDetailBeanV2> list = new ArrayList<>();
        for (BpContractorStaff staff : staffs) {
            LocateStaffDetailBeanV2 bean = new LocateStaffDetailBeanV2();
            BeanUtils.copyProperties(staff, bean);
            //证件类型
            bean.setIdCardType(staff.getIdCardType() == null ? null : BaseIdCardTypes.getIdName(new Integer(staff.getIdCardType().intValue())));
            //姓名
            bean.setRealName(staff.getName());
            //身份
            bean.setRole(staff.getIdentity().longValue());
            //工作单位
            Long contractorId = staff.getContractorId();
            if (contractorId != null) {
                bpContractorDao.findById(contractorId).ifPresent(r -> bean.setWorkCompany(r.getCompanyName()));
            }
//            //取同步成功的一个岗位
//            BpJob job = bpJobDao.getSyncOne();
//            if (job != null) {
//                bean.setJob(job.getUniqueId());
//            }
            //岗位写死名称：  承包商岗位
            bean.setJob("承包商岗位");

            //部门取我们的顶级部门
            List<BpDepart> departList = bpDepartDao.findByParentIsNull();
            if (!CollectionUtils.isEmpty(departList)) {
                bean.setDepartId(departList.get(0).getUniqueId());
            }

            //民族
            Long nation = staff.getNation();
            if (nation != null && nation != 0) {
                typeGroupItemDao.findById(nation).ifPresent(r -> bean.setNationName(r.getName()));
            }
            //参加工作时间
            LocalDate joinWorkDate = staff.getJoinWorkDate();
            if (joinWorkDate != null) {
                bean.setJoinWorkDate(joinWorkDate.toString());
            }
            //人员详情链接
            bean.setUrl(staff.getRefUrl());
            //健康状态
            Long healthStatus = staff.getHealthStatus();
            if (healthStatus != null && healthStatus != 0) {
                typeGroupItemDao.findById(healthStatus).ifPresent(r -> bean.setHealthStatusName(r.getName()));

            }
            //学历
            Long education = staff.getEducation();
            if (education != null && education != 0) {
                typeGroupItemDao.findById(education).ifPresent(r -> bean.setEducationName(r.getName()));

            }
            //人员模板
            Long alarmTemplateId = staff.getAlarmTemplateId();
            if (alarmTemplateId != null) {
                bean.setPersonTemplateId(alarmTemplateId.intValue());
            } else {
                bean.setPersonTemplateId(null);
            }
            //户籍所在地
            bean.setCensus(staff.getCensusRegister());
            //从业所在地
            bean.setWork(staff.getWorkAt());
            //门禁卡号
            bean.setCardNumber(staff.getCardNumber());
            if (staff.getCapId() != null) {
                bean.setIconId(baseImageRespositoryDao.getUniqueIdById(staff.getCapId()));
            }
            list.add(bean);
        }
        return list;
    }

    /**
     * 根据uniqueId判断人员是否存在，同样适用承包商人员
     */
    private boolean isUserExist(String loginToken, String buildId, BaseConfig searchConfig, Long uniqueId) {
        String searchUrl = getIpPortUrl(searchConfig.getValue());
        LocateSearchBeanV2 searchBeanV2 = new LocateSearchBeanV2(uniqueId, buildId);
        boolean exist = false;
        ResponseEntity<LocateLoginRespDto> searchResponse = rest(searchBeanV2, loginToken, searchUrl, LocateLoginRespDto.class);
        if (searchResponse.getStatusCode() != null || searchResponse.getStatusCode().value() == HttpStatus.OK.value()) {
            LocateLoginRespDto body = searchResponse.getBody();
            if (body != null && body.getCode() == 0 && body.getData() != null) {
                exist = true;
            }
        }
        return exist;
    }

    //flag 0 人员;1 承包商人员
    //切换工作单位时先去定位系统删除之前单位的人员数据再去新增一条新的数据
    @Override
    public void syncLocateUsers(List<?> newList, Long newTenentId, String newOrgCode, String oldOrgCode, Long oldTenentId, String oldUniqueId, String oldBuildId, String newBuildId) {
        if (CollectionUtils.isEmpty(newList)) {
            return;
        }
        log.info("开始同步人员...");
        final List<BaseUser> newBaseUserList = Lists.newArrayList();
        newBaseUserList.addAll((List<BaseUser>) newList);
        BuildDataDto dto = new BuildDataDto();
        dto.setTenentId(newTenentId);
        dto.setOrgCode(newOrgCode);
        String locateVersion = getApiLocateVersion(dto);
        if ("4.x".equals(locateVersion)) {
            //同步人员
            syncLocateUsersV3(newBaseUserList.get(0), newTenentId, newOrgCode, oldOrgCode, oldTenentId, oldUniqueId, oldBuildId, newBuildId);
            return;
        }
    }

    public void syncLocateUsersV3(BaseUser newUser, Long newTenentId, String newOrgCode, String oldOrgCode, Long oldTenentId, String oldUniqueId, String oldBuildId, String newBuildId) {
        if (newUser == null || newUser.getUniqueId() == null || oldUniqueId == null) {
            return;
        }
        log.info("开始同步人员...");
        //删除旧数据
//        if (oldUser.isLocateSync()) {
//            return;
//        }
//        Context.setTenentIdOrgCodeIntercept(false);
        BuildDataDto dto = new BuildDataDto();
        dto.setTenentId(oldTenentId);
        dto.setOrgCode(oldOrgCode);
        String loginToken = getLoginTokenCross(oldTenentId, oldOrgCode, oldBuildId);
        if (loginToken == null) {
            log.error("同步人员v2,loginToken为空,检查系统配置和网络...");
            return;
        }
        if (StringUtil.isEmpty(oldBuildId)) return;
        ApiBaseConfigBean deleteConfigDto = apiBaseConfigMapper.findConfig(oldTenentId, oldOrgCode, BaseConfigCodes.LOCATE_SERVER_V2_EMPLOYEE_BATCH_DELETE);
        BaseConfig deleteConfig = new BaseConfig();
        BeanUtils.copyProperties(deleteConfigDto, deleteConfig);
        if (deleteConfig == null) return;
        String deleteUrl = getApiIpPortUrl(deleteConfig.getValue(), dto);

        LocateUserBean<String> bean = new LocateUserBean<>(oldBuildId, Lists.newArrayList(oldUniqueId));
        ResponseEntity<LocateLoginRespDto> response = rest(bean, loginToken, deleteUrl, LocateLoginRespDto.class);
        if (response.getStatusCode() != null && response.getStatusCode().value() == HttpStatus.OK.value()) {
            LocateLoginRespDto body = response.getBody();
            if (body != null && body.getCode() == 0) {
                log.info("同步人员v2，删除success，userId:{},errorBody:{}", oldUniqueId, response);
//                oldUser.setLocateSync(true);
                //添加新数据
                byte failFlag = 1;
                loginToken = getLoginTokenCross(newTenentId, newOrgCode, newBuildId);
                BuildDataDto newDto = new BuildDataDto();
                newDto.setTenentId(newTenentId);
                newDto.setOrgCode(newOrgCode);

                //同步人员信息
                List<SyncBatchDataReturnBean> returnBeans = this.apiSyncSaveUser(Lists.newArrayList(newUser), newBuildId, loginToken, newDto);
                if (CollectionUtils.isEmpty(returnBeans)) {
                    failFlag = 0;
                }
                //同步人员头像
                if (failFlag == 0) {
                    failFlag = baseImageSyncService.apiSyncPeopleHeadImage(newUser.getIdCardImgId(), newUser.getUniqueId(), newBuildId, loginToken, failFlag, newDto);
                }
                //调用接口失败
                if (failFlag == 1) {
                    newUser.setLocateSync(false);
                    ApiBaseUserBean userBean = new ApiBaseUserBean();
                    BeanUtils.copyProperties(newUser, userBean);
                    baseUserMapper.updateById(userBean);
//                    baseUserDao.save(newUser);
                    log.info("同步人员v3, 同步失败, userId:" + newUser.getId());
                } else {
                    newUser.setLocateSync(true);
//                    baseUserDao.save(newUser);
                    baseUserMapper.updateSyncState(newUser.getId());
                    log.info("同步人员v3, 同步成功, userId:" + newUser.getId());
                }
            } else {
                log.error("同步人员v2，删除fail，userId:{},errorBody:{}", oldUniqueId, response);
//                oldUser.setLocateSync(false);
            }
        } else {
            log.info("同步人员v2，删除fail，userId:{},errorBody:{}", oldUniqueId, response);
//            oldUser.setLocateSync(false);
        }
//        Context.setTenentIdOrgCodeIntercept(true);
    }

    //flag 0 人员;1 承包商人员
    @Override
    public void syncLocateUsers(List<?> list, Integer flag) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        log.info("开始同步人员...");
        final List<BaseUser> baseUserList = Lists.newArrayList();
        final List<BpContractorStaff> staffList = Lists.newArrayList();
        int size = list.size();
        if (flag == 0) {
            baseUserList.addAll((List<BaseUser>) list);
        } else {
            staffList.addAll((List<BpContractorStaff>) list);
        }
        String locateVersion = getLocateVersion();
        if ("4.x".equals(locateVersion)) {
            //同步人员
            if (flag == 0) {
                if (baseUserList.size() == 1) {
                    syncLocateUsersV2(baseUserList.get(0), 0);
                    return;
                } else {
                    syncLocateUsersV2(baseUserList);
                    return;
                }
            }
            //同步承包商
            else if (flag == 1) {
                if (staffList.size() == 1) {
                    syncLocateStaffV2(staffList.get(0), 0);
                    return;
                } else {
                    syncLocateStaffV2(staffList);
                    return;
                }
            }
        }
        if (flag == 0) {
            //工种
            List<Long> workTypeIds = baseUserList.stream().map(r -> r.getWorkTypeId()).filter(Objects::nonNull)
                    .distinct().collect(Collectors.toList());
            Map<Long, String> workTypeMap = bpWorkTypeDao.findAllById(workTypeIds).stream().collect(Collectors.toMap(BpWorkType::getId, BpWorkType::getName));
            //部门
            List<Long> departIds = baseUserList.stream().map(r -> r.getDepartId()).filter(Objects::nonNull)
                    .distinct().collect(Collectors.toList());
            Map<Long, String> departMap = departDao.findAllById(departIds).stream().collect(Collectors.toMap(BpDepart::getId, BpDepart::getName));
            baseUserList.forEach(r -> {
                r.setWorkType(workTypeMap.getOrDefault(r.getWorkTypeId(), ""));
                r.setDepartName(departMap.getOrDefault(r.getDepartId(), ""));
            });

        }
        ShiroUser currentUser = Context.getCurrentUser();
        log.info(".... currentUser tenentId={}, orgCode={}", currentUser.getTenentId(), currentUser.getCompanyCode());
        executor.execute(() -> {

//            Context.setCurrentUser(currentUser);
            String loginToken = getLoginToken(currentUser.getTenentId(), currentUser.getCompanyCode());
            if (loginToken == null) {
                return;
            }

            BaseConfig ipConfig = baseConfigService.findConfig(currentUser.getTenentId(), currentUser.getCompanyCode(), BaseConfigCodes.LOCATE_SERVER_URL);
            BaseConfig buildIdConfig = baseConfigService.findConfig(currentUser.getTenentId(), currentUser.getCompanyCode(), BaseConfigCodes.LOCATE_CURRENT_BUILD_ID);

            //修改前先设置base_user表字段employee_id
            BaseConfig searchConfig = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_SERVER_EMPLOYEE_SEARCH);
            String searchUrl = null;
            if (searchConfig != null && ipConfig != null) {
                searchUrl = getHttpIpPort(ipConfig.getValue()) + searchConfig.getValue();
            }
            if (flag == 0 && searchUrl != null) {
                syncEmployeeId(loginToken, buildIdConfig, list, searchUrl, 0);
            } else if (flag == 1 && searchUrl != null) {
                syncEmployeeId(loginToken, buildIdConfig, list, searchUrl, 1);
            }

            BaseConfig addConfig = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_SERVER_EMPLOYEE_ADD);
            BaseConfig editConfig = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_SERVER_EMPLOYEE_EDIT);
            BaseConfig deleteConfig = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_SERVER_EMPLOYEE_DELETE);
            if (terminateFun(ipConfig, addConfig, buildIdConfig, editConfig, deleteConfig)) {
                log.info("addConfig or editConfig or deleteConfig == null");
                return;
            }
            String userAddUrl = getHttpIpPort(ipConfig.getValue()) + addConfig.getValue();
            String buildId = buildIdConfig.getValue();
            String userEditUrl = getHttpIpPort(ipConfig.getValue()) + editConfig.getValue();
            String userDeleteUrl = getHttpIpPort(ipConfig.getValue()) + deleteConfig.getValue();


            List<BaseUser> needUserUpdateList = Lists.newArrayList();
            List<BpContractorStaff> needStaffUpdateList = Lists.newArrayList();
            CountDownLatch countDownLatch = new CountDownLatch(size);
            if (flag == 0) {
                for (BaseUser user : baseUserList) {
                    asyncUserTask(loginToken, userAddUrl, buildId, userEditUrl, userDeleteUrl, needUserUpdateList, countDownLatch, user);
                }
            } else if (flag == 1) {
                for (BpContractorStaff staff : staffList) {
                    asyncStaffTask(loginToken, userAddUrl, buildId, userEditUrl, userDeleteUrl, needStaffUpdateList, countDownLatch, staff);
                }
            }

            try {
                countDownLatch.await(10, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (flag == 0) {
                baseUserDao.saveAll(needUserUpdateList);
            } else if (flag == 1) {
                staffDao.saveAll(needStaffUpdateList);
            }
            log.info("同步人员结束...");
        });
    }

    //flag 0 人员;1 承包商人员
    @Override
    public void apiSyncLocateUsers(List<?> list, Integer flag, BuildDataDto buildDataDto) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        log.info("开始同步人员...");
        final List<ApiBaseUserBean> baseUserList = Lists.newArrayList();
        final List<BpContractorStaff> staffList = Lists.newArrayList();
        int size = list.size();
        if (flag == 0) {
            baseUserList.addAll((List<ApiBaseUserBean>) list);
        } else {
            staffList.addAll((List<BpContractorStaff>) list);
        }
        String locateVersion = getApiLocateVersion(buildDataDto);
        if ("4.x".equals(locateVersion)) {
            //同步人员
            if (flag == 0) {
                if (baseUserList.size() == 1) {
                    BaseUser user = new BaseUser();
                    BeanUtils.copyProperties(baseUserList.get(0), user);
                    apiSyncLocateUsersV2(user, 0, buildDataDto);
                    return;
                }
            }
            //同步承包商
            else if (flag == 1) {
                if (staffList.size() == 1) {
                    syncLocateStaffV2(staffList.get(0), 0);
                    return;
                } else {
                    syncLocateStaffV2(staffList);
                    return;
                }
            }
        }
        if (flag == 0) {
            //工种
            List<Long> workTypeIds = baseUserList.stream().map(r -> r.getWorkTypeId()).filter(Objects::nonNull)
                    .distinct().collect(Collectors.toList());
            Map<Long, String> workTypeMap = workTypeMapper.selectBatchIds(workTypeIds).stream().collect(Collectors.toMap(ApiBpWorkTypeBean::getId, ApiBpWorkTypeBean::getName));
            //部门
            List<Long> departIds = baseUserList.stream().map(r -> r.getDepartId()).filter(Objects::nonNull)
                    .distinct().collect(Collectors.toList());
            Map<Long, String> departMap = departMapper.selectBatchIds(departIds).stream().collect(Collectors.toMap(ApiBpDepartBean::getId, ApiBpDepartBean::getName));
            baseUserList.forEach(r -> {
                r.setWorkType(workTypeMap.getOrDefault(r.getWorkTypeId(), ""));
//                r.setDepartName(departMap.getOrDefault(r.getDepartId(), ""));
            });

        }
//        ShiroUser currentUser = Context.getCurrentUser();
        executor.execute(() -> {
//            Context.setCurrentUser(currentUser);
            String loginToken = getApiLoginToken(buildDataDto);
            if (loginToken == null) {
                return;
            }

            ApiBaseConfigBean ipConfig = configMapper.findConfig(buildDataDto.getTenentId(), buildDataDto.getOrgCode(), BaseConfigCodes.LOCATE_SERVER_URL);
            ApiBaseConfigBean buildIdConfig = configMapper.findConfig(buildDataDto.getTenentId(), buildDataDto.getOrgCode(), BaseConfigCodes.LOCATE_CURRENT_BUILD_ID);

            //修改前先设置base_user表字段employee_id
            ApiBaseConfigBean searchConfig = configMapper.findConfig(buildDataDto.getTenentId(), buildDataDto.getOrgCode(), BaseConfigCodes.LOCATE_SERVER_EMPLOYEE_SEARCH);
            String searchUrl = null;
            if (searchConfig != null && ipConfig != null) {
                searchUrl = getApiHttpIpPort(ipConfig.getValue(), buildDataDto.getTenentId(), buildDataDto.getOrgCode()) + searchConfig.getValue();
            }
//            if (flag == 0 && searchUrl != null) {
//                List<BaseUser> userList = baseUserDao.findBySnNotNullAndEmployeeIdNull();
//                if (!CollectionUtils.isEmpty(userList)) {
//                    syncEmployeeId(loginToken, buildIdConfig, userList, searchUrl, 0);
//                }
//            } else if (flag == 1 && searchUrl != null) {
//                List<BpContractorStaff> contractorStaffList = staffDao.findBySnNotNullAndEmployeeIdNull();
//                if (!CollectionUtils.isEmpty(contractorStaffList)) {
//                    syncEmployeeId(loginToken, buildIdConfig, contractorStaffList, searchUrl, 1);
//                }
//            }

            ApiBaseConfigBean addConfig = configMapper.findConfig(buildDataDto.getTenentId(), buildDataDto.getOrgCode(), BaseConfigCodes.LOCATE_SERVER_EMPLOYEE_ADD);
            ApiBaseConfigBean editConfig = configMapper.findConfig(buildDataDto.getTenentId(), buildDataDto.getOrgCode(), BaseConfigCodes.LOCATE_SERVER_EMPLOYEE_EDIT);
            ApiBaseConfigBean deleteConfig = configMapper.findConfig(buildDataDto.getTenentId(), buildDataDto.getOrgCode(), BaseConfigCodes.LOCATE_SERVER_EMPLOYEE_DELETE);
            if (apiTerminateFun(ipConfig, addConfig, buildIdConfig, editConfig, deleteConfig)) {
                log.info("addConfig or editConfig or deleteConfig == null");
                return;
            }
            String userAddUrl = getApiHttpIpPort(ipConfig.getValue(), buildDataDto.getTenentId(), buildDataDto.getOrgCode()) + addConfig.getValue();
            String buildId = buildIdConfig.getValue();
            String userEditUrl = getApiHttpIpPort(ipConfig.getValue(), buildDataDto.getTenentId(), buildDataDto.getOrgCode()) + editConfig.getValue();
            String userDeleteUrl = getApiHttpIpPort(ipConfig.getValue(), buildDataDto.getTenentId(), buildDataDto.getOrgCode()) + deleteConfig.getValue();

            //存在人员/承包商人员，sn切换的情况
            //小英：人员如果要切换sn会先将其sn置空，这时将所有sn为空employeeId不为空的人员删除后再新增
            if (flag == 0 && userDeleteUrl != null) {
                List<ApiBaseUserBean> needDeleteUsers = baseUserMapper.findBySnNullAndEmployeeIdNotNull();
                for (ApiBaseUserBean needDeleteUser : needDeleteUsers) {
                    LocateUserBean<String> bean = new LocateUserBean<>(buildId, Lists.newArrayList(needDeleteUser.getEmployeeId()));
                    ResponseEntity<LocateUserRespDto> response = rest(bean, loginToken, userDeleteUrl, LocateUserRespDto.class);
                    if (response.getStatusCode() != null && response.getStatusCode().value() == HttpStatus.OK.value() &&
                            response.getBody().getErrmsg() == null) {
                        needDeleteUser.setLocateSync(false);
                        log.info("人员在岗在位人员同步，删除sn=null&&employeeId!=null的人员，删除success，userId:{},response:{}", needDeleteUser.getId(), response);
                    } else {
                        log.info("人员在岗在位人员同步，删除sn=null&&employeeId!=null的人员，删除fail，userId:{},response:{}", needDeleteUser.getId(), response);
                    }
                    baseUserMapper.insert(needDeleteUser);
                }
            }

            List<ApiBaseUserBean> needUserUpdateList = Lists.newArrayList();
            List<BpContractorStaff> needStaffUpdateList = Lists.newArrayList();
            CountDownLatch countDownLatch = new CountDownLatch(size);
            if (flag == 0) {
                for (ApiBaseUserBean user : baseUserList) {
                    asyncApiUserTask(loginToken, userAddUrl, buildId, userEditUrl, userDeleteUrl, needUserUpdateList, countDownLatch, user);
                }
            } else if (flag == 1) {
                for (BpContractorStaff staff : staffList) {
                    asyncStaffTask(loginToken, userAddUrl, buildId, userEditUrl, userDeleteUrl, needStaffUpdateList, countDownLatch, staff);
                }
            }

            try {
                countDownLatch.await(10, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (flag == 0) {
                needUserUpdateList.forEach(r -> {
                    baseUserMapper.insert(r);
                });
//                baseUserDao.saveAll(needUserUpdateList);
            } else if (flag == 1) {
                staffDao.saveAll(needStaffUpdateList);
            }
            log.info("同步人员结束...");
        });
    }

    //flag 0 人员; 1 承包商人员
    private void syncEmployeeId(String loginToken, BaseConfig buildIdConfig, List<?> list, String
            searchUrl, Integer flag) {
        List<BaseUser> userList = null;
        List<BpContractorStaff> staffList = null;
        List<Long> logUserIds;
        if (flag == 0) {
            userList = (List<BaseUser>) list;
            logUserIds = userList.stream().map(r -> r.getId()).collect(Collectors.toList());
        } else {
            staffList = (List<BpContractorStaff>) list;
            logUserIds = staffList.stream().map(r -> r.getId()).collect(Collectors.toList());
        }
        LocateUserBean<Void> bean = new LocateUserBean<>(buildIdConfig.getValue(), null);
        ResponseEntity<LocateUserRespDto> response = rest(bean, loginToken, searchUrl, LocateUserRespDto.class);
        if (response.getStatusCode() == null || response.getStatusCode() != HttpStatus.OK ||
                response.getBody().getErrmsg() != null) {
            log.info("人员在岗在位人员同步，查询fail，response:{}", response);
        } else {
            List<LinkedHashMap> data = (List<LinkedHashMap>) response.getBody().getData();
            Map<String, String> snMap = new HashMap<>(data.size());
            data.forEach(r -> {
                String employeeId = (String) r.get("employeeId");
                String sn = (String) r.get("sn");
                snMap.put(sn, employeeId);
            });
            if (flag == 0) {
                userList.forEach(r -> {
                    String employeeId = snMap.get(r.getSn());
                    if (employeeId != null) {
                        r.setEmployeeId(employeeId);
                        r.setLocateSync(true);
                    }
                });
                baseUserDao.saveAll(userList);
            } else if (flag == 1) {
                staffList.forEach(r -> {
                    String employeeId = snMap.get(r.getSn());
                    if (employeeId != null) {
                        r.setEmployeeId(employeeId);
                        r.setLocateSync(true);
                    }
                });
                staffDao.saveAll(staffList);
            }
            log.info("人员在岗在位人员同步，同步 {}employeeId， userIds:{}", flag == 0 ? "人员" : "承包商人员", logUserIds);
        }
    }

    private boolean terminateFun(BaseConfig... configs) {
        for (BaseConfig config : configs) {
            if (config == null) {
                return true;
            }
        }
        return false;
    }

    private boolean apiTerminateFun(ApiBaseConfigBean... configs) {
        for (ApiBaseConfigBean config : configs) {
            if (config == null) {
                return true;
            }
        }
        return false;
    }


    private void asyncApiUserTask(String loginToken, String userAddUrl, String buildId, String userEditUrl, String
            userDeleteUrl,
                                  List<ApiBaseUserBean> needUserUpdateList, CountDownLatch countDownLatch, ApiBaseUserBean user) {
        executor.execute(() -> {
            try {
                //删除
                if (DataStateTypes.DELETE.getState().equals(user.getState()) && user.getEmployeeId() != null) {
                    LocateUserBean<String> bean = new LocateUserBean<>(buildId, Lists.newArrayList(user.getEmployeeId()));
                    ResponseEntity<LocateUserRespDto> response = rest(bean, loginToken, userDeleteUrl, LocateUserRespDto.class);
                    if (response.getStatusCode() == null || response.getStatusCode() != HttpStatus.OK ||
                            response.getBody().getErrmsg() != null) {
                        log.info("人员在岗在位人员同步，删除fail，userId:{},response:{}", user.getId(), response);
                    } else {
                        log.info("人员在岗在位人员同步，删除success，userId:{}", user.getId());
                    }
                } else {
                    LocateUserBean<LocateUserDetailBean> bean = new LocateUserBean(buildId,
                            Lists.newArrayList(new LocateUserDetailBean(user)));
                    //同步过的调修改接口
                    if (user.getLocateSync()) {
                        ResponseEntity<LocateUserRespDto> response = rest(bean, loginToken, userEditUrl, LocateUserRespDto.class);
                        if (response.getStatusCode() == null || response.getStatusCode() != HttpStatus.OK ||
                                response.getBody().getErrmsg() != null) {
                            log.info("人员在岗在位人员同步，修改fail，userId:{},response:{}", user.getId(), response);
                            //errorCode 10021 表示人员employee_id不存在，这时需要重新新增此人员
                            //这种情况存在于，在人员在岗在位删除了此人员，五位一体还存在
                            if (response.getBody().getErrorCode() == 10021 && response.getBody().getErrmsg() != null) {
                                user.setEmployeeId(null);
                                baseUserMapper.insert(user);
                                bean = new LocateUserBean(buildId, Lists.newArrayList(new LocateUserDetailBean(user)));
                                addApiRest(loginToken, userAddUrl, needUserUpdateList, null, user, bean, 0);
                            }
                        } else {
                            log.info("人员在岗在位人员同步，修改success，userId:{}", user.getId());
                        }
                    } else {
                        addApiRest(loginToken, userAddUrl, needUserUpdateList, null, user, bean, 0);
                    }
                }
            } catch (Exception e) {
                log.error("人员在岗在位人员同步，接口调用fail，errorMsg:", e.getMessage());
            }
            countDownLatch.countDown();
        });
    }

    private void asyncUserTask(String loginToken, String userAddUrl, String buildId, String userEditUrl, String
            userDeleteUrl,
                               List<BaseUser> needUserUpdateList, CountDownLatch countDownLatch, BaseUser user) {
        executor.execute(() -> {
            try {
                //删除
                if (DataStateTypes.DELETE.getState().equals(user.getState()) && user.getEmployeeId() != null) {
                    LocateUserBean<String> bean = new LocateUserBean<>(buildId, Lists.newArrayList(user.getEmployeeId()));
                    ResponseEntity<LocateUserRespDto> response = rest(bean, loginToken, userDeleteUrl, LocateUserRespDto.class);
                    if (response.getStatusCode() == null || response.getStatusCode() != HttpStatus.OK ||
                            response.getBody().getErrmsg() != null) {
                        log.info("人员在岗在位人员同步，删除fail，userId:{},response:{}", user.getId(), response);
                    } else {
                        log.info("人员在岗在位人员同步，删除success，userId:{}", user.getId());
                    }
                } else {
                    LocateUserBean<LocateUserDetailBean> bean = new LocateUserBean(buildId,
                            Lists.newArrayList(new LocateUserDetailBean(user)));
                    //同步过的调修改接口
                    if (user.isLocateSync()) {
                        ResponseEntity<LocateUserRespDto> response = rest(bean, loginToken, userEditUrl, LocateUserRespDto.class);
                        if (response.getStatusCode() == null || response.getStatusCode() != HttpStatus.OK ||
                                response.getBody().getErrmsg() != null) {
                            log.info("人员在岗在位人员同步，修改fail，userId:{},response:{}", user.getId(), response);
                            //errorCode 10021 表示人员employee_id不存在，这时需要重新新增此人员
                            //这种情况存在于，在人员在岗在位删除了此人员，五位一体还存在
                            if (response.getBody().getErrorCode() == 10021 && response.getBody().getErrmsg() != null) {
                                user.setEmployeeId(null);
                                baseUserDao.save(user);
                                bean = new LocateUserBean(buildId, Lists.newArrayList(new LocateUserDetailBean(user)));
                                addRest(loginToken, userAddUrl, needUserUpdateList, null, user, bean, 0);
                            }
                        } else {
                            log.info("人员在岗在位人员同步，修改success，userId:{}", user.getId());
                        }
                    } else {
                        addRest(loginToken, userAddUrl, needUserUpdateList, null, user, bean, 0);
                    }
                }
            } catch (Exception e) {
                log.error("人员在岗在位人员同步，接口调用fail，errorMsg:", e.getMessage());
            }
            countDownLatch.countDown();
        });
    }

    private void asyncStaffTask(String loginToken, String userAddUrl, String buildId, String userEditUrl, String
            userDeleteUrl,
                                List<BpContractorStaff> needStaffUpdateList, CountDownLatch countDownLatch, BpContractorStaff staff) {
        executor.execute(() -> {
            try {
                //删除  --3.4化工：人员删除会相应解绑sn
                if (DataStateTypes.UN_EFFECTIVE.getState().equals(staff.getState()) && staff.getEmployeeId() != null) {
                    LocateUserBean<String> bean = new LocateUserBean<>(buildId, Lists.newArrayList(staff.getEmployeeId()));
                    ResponseEntity<LocateUserRespDto> response = rest(bean, loginToken, userDeleteUrl, LocateUserRespDto.class);
                    if (response.getStatusCode() == null || response.getStatusCode() != HttpStatus.OK ||
                            response.getBody().getErrmsg() != null) {
                        log.info("人员在岗在位人员同步，承包商人员，删除fail，staffId:{},response:{}", staff.getId(), response);
                    } else {
                        log.info("人员在岗在位人员同步，承包商人员，删除success，staffId:{}", staff.getId());
                    }
                } else {
                    LocateUserBean<LocateUserDetailBean> bean = new LocateUserBean(buildId,
                            Lists.newArrayList(new LocateUserDetailBean(staff)));
                    //同步过的调修改接口
                    if (staff.isLocateSync()) {
                        ResponseEntity<LocateUserRespDto> response = rest(bean, loginToken, userEditUrl, LocateUserRespDto.class);
                        if (response.getStatusCode() == null || response.getStatusCode() != HttpStatus.OK ||
                                response.getBody().getErrmsg() != null) {
                            log.info("人员在岗在位人员同步，承包商人员，修改fail，staffId:{},response:{}", staff.getId(), response);
                            //errorCode 10021 表示人员employee_id不存在，这时需要重新新增此人员
                            //这种情况存在于，在人员在岗在位删除了此人员，五位一体还存在
                            if (response.getBody().getErrorCode() == 10021 && response.getBody().getErrmsg() != null) {
                                staff.setEmployeeId(null);
                                staffDao.save(staff);
                                bean = new LocateUserBean(buildId, Lists.newArrayList(new LocateUserDetailBean(staff)));
                                addRest(loginToken, userAddUrl, null, needStaffUpdateList, staff, bean, 1);
                            }
                        } else {
                            log.info("人员在岗在位人员同步，承包商人员，修改success，staffId:{}", staff.getId());
                        }
                    } else {
                        addRest(loginToken, userAddUrl, null, needStaffUpdateList, staff, bean, 1);
                    }
                }
            } catch (Exception e) {
                log.error("人员在岗在位承包商人员同步，接口调用fail，errorMsg:", e.getMessage());
            }
            countDownLatch.countDown();
        });
    }

    //flag 0 人员; 1 承包商人员
    private void addRest(String loginToken, String
            userAddUrl, List<BaseUser> needUserUpdateList, List<BpContractorStaff> needStaffUpdateList,
                         Object object, LocateUserBean<LocateUserDetailBean> bean, Integer flag) {
        BaseUser user = null;
        BpContractorStaff staff = null;
        if (flag == 0) {
            user = (BaseUser) object;
        } else if (flag == 1) {
            staff = (BpContractorStaff) object;
        }
        ResponseEntity<LocateUserRespDto> response = rest(bean, loginToken, userAddUrl, LocateUserRespDto.class);
        if (response.getStatusCode() != null && response.getStatusCode() == HttpStatus.OK
                && response.getBody().getErrmsg() == null) {
            List<LinkedHashMap> data = (List<LinkedHashMap>) response.getBody().getData();
            String employeeId = (String) data.get(0).get("employeeId");
            if (flag == 0) {
                user.setEmployeeId(employeeId);
                user.setLocateSync(true);
                needUserUpdateList.add(user);
            } else if (flag == 1) {
                staff.setEmployeeId(employeeId);
                staff.setLocateSync(true);
                needStaffUpdateList.add(staff);
            }
            log.info("人员在岗在位人员同步，{} 新增success，userId:{}", flag == 0 ? "人员" : "承包商人员",
                    flag == 0 ? user.getId() : staff.getId());
        } else {
            log.info("人员在岗在位人员同步，{} 新增fail，userId:{},response:{}", flag == 0 ? "人员" : "承包商人员",
                    flag == 0 ? user.getId() : staff.getId(), response);
        }
    }

    //flag 0 人员; 1 承包商人员
    private void addApiRest(String loginToken, String
            userAddUrl, List<ApiBaseUserBean> needUserUpdateList, List<BpContractorStaff> needStaffUpdateList,
                            Object object, LocateUserBean<LocateUserDetailBean> bean, Integer flag) {
        ApiBaseUserBean user = null;
        BpContractorStaff staff = null;
        if (flag == 0) {
            user = (ApiBaseUserBean) object;
        } else if (flag == 1) {
            staff = (BpContractorStaff) object;
        }
        ResponseEntity<LocateUserRespDto> response = rest(bean, loginToken, userAddUrl, LocateUserRespDto.class);
        if (response.getStatusCode() != null && response.getStatusCode() == HttpStatus.OK
                && response.getBody().getErrmsg() == null) {
            List<LinkedHashMap> data = (List<LinkedHashMap>) response.getBody().getData();
            String employeeId = (String) data.get(0).get("employeeId");
            if (flag == 0) {
                user.setEmployeeId(employeeId);
                user.setLocateSync(true);
                needUserUpdateList.add(user);
            } else if (flag == 1) {
                staff.setEmployeeId(employeeId);
                staff.setLocateSync(true);
                needStaffUpdateList.add(staff);
            }
            log.info("人员在岗在位人员同步，{} 新增success，userId:{}", flag == 0 ? "人员" : "承包商人员",
                    flag == 0 ? user.getId() : staff.getId());
        } else {
            log.info("人员在岗在位人员同步，{} 新增fail，userId:{},response:{}", flag == 0 ? "人员" : "承包商人员",
                    flag == 0 ? user.getId() : staff.getId(), response);
        }
    }

    /**
     * 连接时间 15
     */
    @Override
    public <T> ResponseEntity<T> rest(Object bean, String loginToken, String url, Class T) {
        HttpHeaders headers = new HttpHeaders();
        headers.set("token", loginToken);
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity httpEntity = new HttpEntity(bean, headers);
        ResponseEntity<T> response = this.restTemplate.postForEntity(url, httpEntity, T);
        return response;
    }

    /**
     * 连接时间 90
     */
    private <T> ResponseEntity<T> batchRest(Object bean, String loginToken, String url, Class T) {
        HttpHeaders headers = new HttpHeaders();
        headers.set("token", loginToken);
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity httpEntity = new HttpEntity(bean, headers);
        ResponseEntity<T> response = this.batchRestTemplate.postForEntity(url, httpEntity, T);
        return response;
    }


    @Override
    public <T> ResponseEntity<T> restPost(Object bean, String urlKey, Class T) {
        try {
            String loginToken = getLoginToken();
            BaseConfig ipConfig = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_SERVER_URL);
            BaseConfig apiConfig = baseConfigService.findFirstConfig(urlKey);
            if (ipConfig == null || apiConfig == null || StringUtils.isEmpty(ipConfig.getValue()) || StringUtils.isEmpty(apiConfig.getValue())) {
                log.info("人员在岗在位同步异常： 接口URL未配置{}", urlKey);
                return null;
            }
            String url = getHttpIpPort(ipConfig.getValue() + apiConfig.getValue());
            return rest(bean, loginToken, url, T);
        } catch (Exception e) {
            log.error("人员在岗在位同步异常", e);
            return null;
        }
    }

    @Override
    public <T> ResponseEntity<T> apiRestPost(Object bean, String urlKey, Class T, BuildDataDto dto) {
        try {
            String loginToken = getApiLoginToken(dto);
            ApiBaseConfigBean ipConfig = apiBaseConfigMapper.findConfig(dto.getTenentId(), dto.getOrgCode(), BaseConfigCodes.LOCATE_SERVER_URL);
            ApiBaseConfigBean apiConfig = apiBaseConfigMapper.findConfig(dto.getTenentId(), dto.getOrgCode(), urlKey);
            if (ipConfig == null || apiConfig == null || StringUtils.isEmpty(ipConfig.getValue()) || StringUtils.isEmpty(apiConfig.getValue())) {
                log.info("人员在岗在位同步异常： 接口URL未配置{}", urlKey);
                return null;
            }
            String url = getApiHttpIpPort(ipConfig.getValue() + apiConfig.getValue(), dto.getTenentId(), dto.getOrgCode());
            return rest(bean, loginToken, url, T);
        } catch (Exception e) {
            log.error("人员在岗在位同步异常", e);
            return null;
        }
    }


    @Override
    public <T> ResponseEntity<T> restPostCross(Object bean, String urlKey, Class T, Long tenentId, String orgCode, String buildId) {
        try {
//            Context.setTenentIdOrgCodeIntercept(false);
            String loginToken = getLoginTokenCross(tenentId, orgCode, buildId);
            ApiBaseConfigBean ipConfigDto = apiBaseConfigMapper.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_SERVER_URL);
            ApiBaseConfigBean apiConfigDto = apiBaseConfigMapper.findConfig(tenentId, orgCode, urlKey);
            BaseConfig ipConfig = new BaseConfig();
            BaseConfig apiConfig = new BaseConfig();
            BeanUtils.copyProperties(ipConfigDto, ipConfig);
            BeanUtils.copyProperties(apiConfigDto, apiConfig);
            if (ipConfig == null || apiConfig == null || StringUtils.isEmpty(ipConfig.getValue()) || StringUtils.isEmpty(apiConfig.getValue())) {
                log.info("人员在岗在位同步异常： 接口URL未配置{}", urlKey);
                return null;
            }
            String url = getApiHttpIpPort(ipConfig.getValue() + apiConfig.getValue(), tenentId, orgCode);
//            Context.setTenentIdOrgCodeIntercept(true);
            return rest(bean, loginToken, url, T);
        } catch (Exception e) {
            log.error("人员在岗在位同步异常", e);
            return null;
        }
    }

    private String getLoginTokenCross(Long tenentId, String orgCode, String buildId) {
//        Long tenantId = object;
//        String orgCode = Context.getCurrentOrgCode().substring(0, 7);
//        String orgCode = Context.getCompanyCode();
        String loginTokenKey = locateLoginTokenKey(tenentId, orgCode);
        String token = redisClient.get(loginTokenKey);
        if (token != null) {
            return token;
        } else {
            String loginToken = getLoginTokenDetailCross(tenentId, orgCode, buildId);
            if (loginToken == null) {
                return null;
            } else {
                //4.x以上2小时，加浩：但是3.4可能比较短些，保险起见30分钟
                redisClient.setEx(loginTokenKey, loginToken, 30, TimeUnit.MINUTES);
                return loginToken;
            }
        }
    }

    /**
     * 标签解绑
     */
    @Override
    public void labelUntie(String sn) {
        String loginToken = getLoginToken();
        String buildId = getBuildId();
        if (loginToken == null || buildId == null) {
            log.error("人员同步v2，标签解绑，loginToken == null or buildId == null");
            return;
        }
        BaseConfig labelUntieConfig = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_SERVER_V2_LABEL_UNTIE);
        if (labelUntieConfig == null) {
            log.error("人员同步v2，标签解绑，未配置标签解绑url...");
            return;
        }
        LocateUserBean<String> userBean = new LocateUserBean<>(buildId, Lists.newArrayList(sn));
        String labelUntieUrl = getIpPortUrl(labelUntieConfig.getValue());
        ResponseEntity<LocateLoginRespDto> response = rest(userBean, loginToken, labelUntieUrl, LocateLoginRespDto.class);
        if (response.getStatusCode() != null && response.getStatusCode().value() == HttpStatus.OK.value()) {
            LocateLoginRespDto body = response.getBody();
            if (body != null && body.getCode() == 0) {
                log.info("人员同步v2，标签解绑，解绑成功, sn:{}", sn);
            } else {
                log.error("人员同步v2，标签解绑，解绑失败, sn:{}，errorBody:{}", sn, body);
                throw new IllegalArgumentException("请填写正确的SN号");
            }
        } else {
            log.error("人员同步v2，标签解绑，解绑失败, sn:{}，errorResponse:{}", sn, response);
            throw new IllegalArgumentException("请填写正确的SN号");
        }
    }

    @Override
    public ResponseEntity orientationSave(Object bean, Class clazz, String flag) {
        String version = getLocateVersion();
        if ("4.x".equals(version)) {
            if (flag == null) {
                return null;
            }
            String url = getUrl(flag, Context.getCurrentTenantId(), Context.getCompanyCode().substring(0, 7));
            String loginToken = getLoginToken();
            if (loginToken == null) {
                log.error("+++++++++++ loginToken is null +++++++++++");
                return null;
            }
            return rest(bean, loginToken, url, clazz);
        }
        return null;
    }

    @Override
    public ResponseEntity orientationSave(Object bean, Class clazz, String flag, Long tenentId, String orgCode) {
        String version = getLocateVersion(tenentId, orgCode);
        if ("4.x".equals(version)) {
            if (flag == null) {
                return null;
            }
            String url = getUrl(flag, tenentId, orgCode);
            String loginToken = getLoginToken(tenentId, orgCode);
            if (loginToken == null) {
                log.error("+++++++++++ loginToken is null +++++++++++");
                return null;
            }
            return rest(bean, loginToken, url, clazz);
        }
        return new ResponseEntity(HttpStatus.OK);
    }

    @Override
    public String getUrl(String flag, Long tenentId, String orgCode) {
        BaseConfig front = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_SERVER_URL);
        BaseConfig rear = null;
        if (flag != null && (flag.equals("addArea") || flag.equals("alterArea"))) {
            rear = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.ORIENTATION_AREA_SAVE_URL);
        } else if (flag != null && flag.equals("deleteArea")) {
            rear = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.ORIENTATION_AREA_DELETE_URL);
        } else if (flag != null && flag.equals("pageAlarmTemplate")) {
            rear = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.ORIENTATION_PAGE_ALARM_TEMPLATE);
        } else if (flag != null && flag.equals("pageCertificateAlarm")) {
            rear = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.ORIENTATION_PAGE_CERTIFICATE_ALARM);
        } else if (flag != null && flag.equals("pageAreaAlarm")) {
            rear = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.ORIENTATION_PAGE_AREA_ALARM);
        } else if (flag != null && flag.equals("solveCertificateAlarm")) {
            rear = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.ORIENTATION_SAVE_CERTIFICATE_ALARM);
        } else if (flag != null && flag.equals("solveAreaAlarm")) {
            rear = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.ORIENTATION_SAVE_AREA_ALARM);
        } else if (flag != null && flag.equals("saveContractor")) {
            rear = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_API_SYNC_CONTRACTOR_SAVE);
        } else if (flag != null && flag.equals("deleteContractor")) {
            rear = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.ORIENTATIONDELETE_DELETE_CONTRACTOR_URL);
        } else if (flag != null && flag.equals("checkSnInArea")) {
            rear = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.ORIENTATIONDELETE_CHECKETE_SN_IN_AREA);
        } else if (flag != null && flag.equals("getAlarmNumber")) {
            rear = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.ORIENTATIONDELETE_ALARM_NUMBER);
        } else if (flag != null && flag.equals("getAlarmTypesNumber")) {
            rear = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.ORIENTATIONDELETE_ALARM_TYPES_NUMBER);
        } else if (flag != null && flag.equals("getV3ScreenToken")) {
            rear = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_V3_SCREEN_GET_TOKEN);
        } else if (flag != null && flag.equals("getV3BindersVersion")) {
            rear = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_V3_BINDERS_VERSION);
        } else if (flag != null && flag.equals("getV3ScreenBinders")) {
            rear = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_V3_SCREEN_BINDERS);
        } else if (flag != null && flag.equals("getV3ScreenAreaPerson")) {
            rear = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_V3_SCREEN_AREA_PERSON);
        } else if (flag != null && flag.equals("getV3ScreenRegionalPopulation")) {
            rear = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_V3_SCREEN_REGIONAL_POPULATION);
        } else if (flag != null && flag.equals("v2Subscribe")) {
            rear = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_V2_SUBSCRIBE);
        } else if (flag != null && flag.equals("v3Subscribe")) {
            rear = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_V3_SUBSCRIBE);
        } else if (flag != null && flag.equals("solveCarAlarm")) {
            rear = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.ORIENTATION_SOLVE_CAR_ALARM);
        }else if (flag != null && flag.equals("v2areaPersonCount")){
            rear = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_V2_AREA_PERSON_COUNT);
        }
        if (front == null || front.getValue() == null || rear == null || rear.getValue() == null) {
            log.error("+++++++++++ BaseConfig is null +++++++++++");
            return "";
        }

        return getHttpIpPort(front.getValue()) + rear.getValue();
    }


    private List<LocateAlarmRecord> convert(List<LinkedHashMap> records) {
        return records == null ? Lists.newArrayList() : records.stream().map(LocateAlarmRecord::new).collect(Collectors.toList());
    }

    /**
     * 获取人员在岗在位buildId
     */
    @Override
    public String getBuildId() {
        BaseConfig buildIdConfig = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_CURRENT_BUILD_ID);
        return buildIdConfig == null ? null : buildIdConfig.getValue();
    }

    @Override
    public String getBuildIdByTenentIdAndOrgCode(Long tenentId, String orgCode) {
        BaseConfig buildIdConfig = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_CURRENT_BUILD_ID);
        return buildIdConfig == null ? null : buildIdConfig.getValue();
    }


    /**
     * 获取人员在岗在位登录凭证token
     * ps: v2版的人员在岗在位，token的有效时间为2小时，在token失效前，需要重新获取token令牌。
     */
    @Override
    public String getLoginToken() {
        Long tenantId = Context.getCurrentTenantId();
        String orgCode = Context.getCompanyCode();
        return getLocateLoginToken(tenantId, orgCode);
    }

    @Override
    public String getLoginTokenForWeb(Long tenentId, String orgCode) {
        return getLocateLoginToken(tenentId, orgCode);
    }

    @Override
    public String getApiLoginToken(BuildDataDto buildDataDto) {
        return getApiLocateLoginToken(buildDataDto);
    }

    private String getApiLocateLoginToken(BuildDataDto buildDataDto) {
        String loginTokenKey = locateLoginTokenKey(buildDataDto.getTenentId(), buildDataDto.getOrgCode());
        String token = redisClient.get(loginTokenKey);
        if (token != null) {
            return token;
        } else {
            String checkKey = checkocateLoginTokenKey(buildDataDto.getTenentId(), buildDataDto.getOrgCode());
            //请求token三次失败 过一分钟再请求
            int checkCount = getCheckCount(buildDataDto.getTenentId(), buildDataDto.getOrgCode(), checkKey);
            if (checkCount < 3) {
                String loginToken = null;
                try {
                    loginToken = getApiLoginTokenDetail(buildDataDto.getTenentId(), buildDataDto.getOrgCode());
                } catch (Exception e) {
                    log.error("get loginToken error " + e);
                }
                if (StringUtils.isBlank(loginToken)) {
                    checkCount++;
                    //一分钟失效
                    log.error("**************获取人员定位Token失败 checkKey = " + checkKey + " checkCount =" + checkCount);
                    redisClient.setEx(checkKey, String.valueOf(checkCount), 1, TimeUnit.MINUTES);
                    return null;
                } else {
                    //获取成功删除key
                    redisClient.removeKey(checkKey);
                    // redisClient.setEx(checkKey, "0", 1, TimeUnit.MINUTES);
                    //4.x以上2小时，加浩：但是3.4可能比较短些，保险起见30分钟
                    redisClient.setEx(loginTokenKey, loginToken, 30, TimeUnit.MINUTES);
                    return loginToken;
                }
            } else {
                log.error("**************获取人员定位Token重试三次失败 checkKey{} " + checkKey);
                return null;
            }
        }
    }

    @Override
    public String getLoginToken(Long tenentId, String orgCode) {
        return getLocateLoginToken(tenentId, orgCode);
    }

    private String getLocateLoginToken(Long tenentId, String orgCode) {
        String loginTokenKey = locateLoginTokenKey(tenentId, orgCode);
        String token = redisClient.get(loginTokenKey);
        if (token != null) {
            return token;
        } else {
            String checkKey = checkocateLoginTokenKey(tenentId, orgCode);
            //请求token三次失败 过一分钟再请求
            int checkCount = getCheckCount(tenentId, orgCode, checkKey);
            if (checkCount < 3) {
                String loginToken = null;
                try {
                    loginToken = getLoginTokenDetail(tenentId, orgCode);
                } catch (Exception e) {
                    log.error("get loginToken error " + e);
                }
                if (StringUtils.isBlank(loginToken)) {
                    checkCount++;
                    //一分钟失效
                    log.error("**************获取人员定位Token失败 checkKey = " + checkKey + " checkCount =" + checkCount);
                    redisClient.setEx(checkKey, String.valueOf(checkCount), 1, TimeUnit.MINUTES);
                    return null;
                } else {
                    //获取成功删除key
                    redisClient.removeKey(checkKey);
                    // redisClient.setEx(checkKey, "0", 1, TimeUnit.MINUTES);
                    //4.x以上2小时，加浩：但是3.4可能比较短些，保险起见30分钟
                    redisClient.setEx(loginTokenKey, loginToken, 30, TimeUnit.MINUTES);
                    return loginToken;
                }
            } else {
                log.error("**************获取人员定位Token重试三次失败 checkKey{} " + checkKey);
                return null;
            }
        }
    }

    private int getCheckCount(Long tenentId, String orgCode, String checkKey) {
        int count = 0;
        String countStr = redisClient.get(checkKey);
        if (StringUtils.isNotBlank(countStr)) {
            count = Integer.valueOf(countStr);
        }
        return count;
    }

    private String locateLoginTokenKey(Long tenantId, String orgCode) {
        return "locate:" + tenantId + ":" + orgCode + ":" + "loginToken";
    }

    private String checkocateLoginTokenKey(Long tenantId, String orgCode) {
        return "locate:" + tenantId + ":" + orgCode + ":" + "checkLoginToken";
    }

    //saveOrDelete 0 add; 1 edit; 2 delete
    @Override
    public String workArea(Object bean, Integer saveOrDelete) {
        String loginToken = getLoginToken();
        if (loginToken == null) {
            log.error("人员在岗在位登录相关配置有问题，或者调不通接口...");
            return null;
        }
        BaseConfig urlConfig;
        String apiType = getApiType(saveOrDelete);
        if (saveOrDelete == 0 || saveOrDelete == 1) {
            urlConfig = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_SERVER_WORK_AREA_SAVE);
        } else {
            urlConfig = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_SERVER_WORK_AREA_DELETE);
        }

        if (urlConfig == null) {
            log.error("人员在岗在位-没配置作业区域 url...");
            return null;
        }
        String ipPortUrl = getIpPortUrl(urlConfig.getValue());
        if (ipPortUrl == null) {
            log.error("人员在岗在位-没配置ipPort url...");
            return null;
        }
        log.info("人员在岗在位-作业票同步传参：{}", JsonUtil.toJson(bean));
        ResponseEntity<LocateLoginRespDto> response = rest(bean, loginToken, ipPortUrl, LocateLoginRespDto.class);
        LocateLoginRespDto dto = response.getBody();
        if (response.getStatusCode() != null && response.getStatusCode() == HttpStatus.OK) {
            if (dto != null && dto.getCode() == 0) {
                //新增：返回uniqueId
                if (saveOrDelete == 0 && dto.getData() != null) {
                    log.info("人员在岗在位-作业区域新增成功, bean:{}", JSON.toJSONString(bean));
                    return dto.getData().toString();
                }
                if (saveOrDelete == 1) {
                    log.info("人员在岗在位-作业区域修改成功, bean:{}", JSON.toJSONString(bean));
                    return "success";
                }
                //删除：无数据返回
                if (saveOrDelete == 2) {
                    log.info("人员在岗在位-作业区域删除成功, bean:{}", JSON.toJSONString(bean));
                    return "success";
                }
            } else {
                log.error("人员在岗在位-作业区域{}失败, errorBody:{}", apiType, dto);
            }
        } else {
            log.error("人员在岗在位-作业区域调接口报错,errorResponse:" + response);
        }
        return null;
    }

    private String getApiType(Integer saveOrDelete) {
        switch (saveOrDelete) {
            case 0:
                return "新增";
            case 1:
                return "修改";
            case 2:
                return "删除";
        }
        return "";
    }

    @Override
    public String getIpPortUrl(String url) {
        BaseConfig ipConfig = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_SERVER_URL);
        if (ipConfig == null) {
            return null;
        }
        return getHttpIpPort(ipConfig.getValue()) + url;
    }

    @Override
    public String getApiIpPortUrl(String url, BuildDataDto dto) {
        ApiBaseConfigBean ipConfig = configMapper.findConfig(dto.getTenentId(), dto.getOrgCode(), BaseConfigCodes.LOCATE_SERVER_URL);
        if (ipConfig == null) {
            return null;
        }
        return getApiHttpIpPort(ipConfig.getValue(), dto.getTenentId(), dto.getOrgCode()) + url;
    }

    @Override
    public int batchUserDelete(List<Long> ids) {
        if (ids.contains(Context.getCurrentUserId())) {
            return -1;
        }
        if (CollectionUtils.isEmpty(ids)) {
            return 0;
        }
        List<BaseUser> users = baseUserDao.findAllById(ids);
        //将全部人设置为待删除
        baseUserDao.setState(ids, DataStateTypes.ON_DELETE.getState());
        //根据uniqueId分组
        List<String> uniqueIds = users.stream().map(e -> e.getUniqueId()).collect(Collectors.toList());
        Map<String, BaseUser> userMap = users.stream().collect(Collectors.toMap(r -> r.getUniqueId(), r -> r));
        Map<Long, BaseUser> userIdMap = users.stream().collect(Collectors.toMap(r -> r.getId(), r -> r));
        if (baseConfigService.checkIfSync()) {
            List<Long> saveIds = new ArrayList<>();
            List<SyncBatchDataReturnBean> returnBeans = Lists.newArrayList();
            try {
                returnBeans = syncDeleteUsers(uniqueIds, "user");
            } catch (Exception e) {
                log.warn("======== 同步删除承包商人员异常");
            }
            if (!CollectionUtils.isEmpty(returnBeans)) {
                for (SyncBatchDataReturnBean bean : returnBeans) {
                    BaseUser user = userMap.get(bean.getUniqueId());
                    if (user != null && user.isLocateSync()) {
                        saveIds.add(user.getId());
                    }
                }
            }
            if (!CollectionUtils.isEmpty(saveIds)) {
                ids.removeAll(saveIds);
                baseUserDao.editLocateSyncByIds(saveIds, 0);
                baseUserDao.setState(saveIds, DataStateTypes.EFFECTIVE.getState());
            }
        }
        if (!CollectionUtils.isEmpty(ids)) {
            baseUserDao.editLocateSyncByIds(ids, 1);
            baseUserDao.setState(ids, DataStateTypes.DELETE.getState());
            baseLoginAccountDao.deleteByIds(ids);
            for (Long id : ids) {
                if (userIdMap.get(id) != null && userIdMap.get(id).getJob() != null) {
                    jobDao.updateJobUserCount(userIdMap.get(id).getJob());
                }
            }
        }
        return ids.size();
    }

    @Override
    public int batchStaffDelete(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return 0;
        }
        List<BpContractorStaff> staffs = staffDao.findAllById(ids);
        //根据uniqueId分组
        List<String> uniqueIds = staffs.stream().map(e -> e.getUniqueId()).collect(Collectors.toList());
        Map<String, BpContractorStaff> staffsMap = staffs.stream().collect(Collectors.toMap(r -> r.getUniqueId(), r -> r));
        if (baseConfigService.checkIfSync()) {
            List<Long> saveIds = new ArrayList<>();
            List<SyncBatchDataReturnBean> returnBeans = Lists.newArrayList();
            try {
                returnBeans = syncDeleteUsers(uniqueIds, "staff");
            } catch (Exception e) {
                log.warn("======== 同步删除承包商人员异常");
            }

            if (!CollectionUtils.isEmpty(returnBeans)) {
                for (SyncBatchDataReturnBean bean : returnBeans) {
                    BpContractorStaff staff = staffsMap.get(bean.getUniqueId());
                    if (staff != null && staff.isLocateSync()) {
                        saveIds.add(staff.getId());
                    }
                }
            }
            if (!CollectionUtils.isEmpty(saveIds)) {
                ids.removeAll(saveIds);
                staffDao.setState(saveIds, DataStateTypes.EFFECTIVE.getState());
            }
        }
        if (!CollectionUtils.isEmpty(ids)) {
            staffDao.setState(ids, DataStateTypes.UN_EFFECTIVE.getState());
            //删除证书
            eduCertificateUserDao.deleteByUserIdsAndUserContractorFlag(ids, 1);
        }
        return ids.size();
    }

    private List<SyncBatchDataReturnBean> syncDeleteUsers(List<String> uniqueIds, String type) {
        log.info("批量删除" + type + "v2Start.....");
        String buildId = getBuildId();
        String loginToken = getLoginToken();
        BaseConfig config = null;
        if (type.equals("user")) {
            config = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_SERVER_V2_EMPLOYEE_BATCH_DELETE);
        } else {
            config = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_SERVER_V2_STAFF_BATCH_DELETE);
        }
        if (config == null) {
            return null;
        }
        SyncBatchUserBean bean = new SyncBatchUserBean();
        bean.setBuildId(buildId);
        bean.setData(uniqueIds);
        if (type.equals("staff")) {
            bean.setStatus(true);
        }
        String url = getIpPortUrl(config.getValue());
        ResponseEntity<LocateLoginRespDto> response = batchRest(bean, loginToken, url, LocateLoginRespDto.class);
        if (response.getStatusCode() != null && response.getStatusCode().value() == HttpStatus.OK.value()) {
            LocateLoginRespDto body = response.getBody();
            if (body != null && body.getCode() == 0) {
                log.info("批量删除" + type + "v2，删除success，uniqueIds:{},errorBody:{}", uniqueIds, response);
                List<SyncBatchDataReturnBean> data = (List<SyncBatchDataReturnBean>) body.getData();
                if (!CollectionUtils.isEmpty(data)) {
                    String str = JSON.toJSONString(data);
                    List<SyncBatchDataReturnBean> list = JSONObject.parseArray(str, SyncBatchDataReturnBean.class);
                    return list;
                }
            } else {
                log.error("批量删除" + type + "v2，删除fail，uniqueIds:{},errorBody:{}", uniqueIds, response);
            }
        } else {
            log.info("批量删除" + type + "v2，删除fail，uniqueIds:{},errorBody:{}", uniqueIds, response);

        }
        log.info("批量删除" + type + "v2End.....");
        return null;
    }

    @Override
    public LocateServerAlarmResult getLocateServerAlarmResult() {
        Long tenentId = Context.getCurrentTenantId();
        String orgCode = Context.getCompanyCode();

        BaseConfig urlConfig = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_SERVER_URL);
        BaseConfig buildIdConfig = baseConfigService.findConfig(tenentId, orgCode,
                BaseConfigCodes.LOCATE_CURRENT_BUILD_ID);
        BaseConfig appIdConfig = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_APP_ID);
        BaseConfig secretConfig = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_SERVER_SECRET);

        String url = urlConfig.getValue();
        String buildId = buildIdConfig.getValue();
        String appId = appIdConfig.getValue();
        String secret = secretConfig.getValue();

        // alarmEvent/list
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        Map<String, Object> ps = new HashMap<>();
        MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
        map.add("buildId", buildId);
        ps.put("buildId", buildId);
        map.add("handled", false);
        ps.put("handled", false);
        map.add("appid", appId);
        ps.put("appid", appId);
        map.add("pageNum", 1);
        ps.put("pageNum", 1);
        map.add("numPerPage", 1000);
        ps.put("numPerPage", 1000);
        String signature = getSignature(ps, secret);
        map.add("signature", signature);
        log.info("params {}, signature {}", JsonUtil.toJson(ps), signature);

        HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(map, headers);

        ResponseEntity<LocateServerAlarmResult> response = restTemplate.postForEntity(getHttpIpPort(url) + "/alarmEvent/list", request,
                LocateServerAlarmResult.class);
        // log.info("8085 alarm events read results {}", response.getStatusCode().toString()
        // + (response.getBody() == null ? " body null" : JsonUtil.toJson(response.getBody())));
        return response.getBody();
    }

    private List<McAlarmMessageBean> convert(LocateServerAlarmResult result) {
        List<McAlarmMessageBean> ls = new ArrayList<>();
        if (result.getData() != null && result.getData().getRecords() != null
                && result.getData().getRecords().getRecordList() != null) {
            List<LocateServerAlarmResultDataRecordsRecordListItem> rs = result.getData().getRecords().getRecordList();
            for (LocateServerAlarmResultDataRecordsRecordListItem i : rs) {
                McAlarmMessageBean alarm = convertAlarm(i);
                if (alarm != null) {
                    ls.add(alarm);
                }
            }
        }
        return ls;
    }

    private McAlarmMessageBean convertAlarm(LocateServerAlarmResultDataRecordsRecordListItem i) {
        if (i != null && i.getRecord() != null) {
            LocateServerAlarmResultDataRecordsRecordListItemRecord record = i.getRecord();
            McAlarmMessageBean bean = new McAlarmMessageBean();
            bean.setExtentId(record.getUuid());
            bean.setModule("人员在岗在位");
            bean.setState(0);
            try {
                bean.setTime(SimpleDateFormatCache.getYmdhms().format(record.getTime()));
            } catch (Exception e) {
            }
            String eventDesc = "";
            String type = "";
            if ("overBoundaryAlarm".equals(record.getType())) {
                type = "越界报警";
                String detail = record.getDetail();
                JsonObject detailObj = new JsonParser().parse(detail).getAsJsonObject();
                String railName = detailObj.get("railName").getAsString();
                eventDesc = String.format("[%s]%s越界！", railName, record.getName());
            } else if ("oneKeyAlarm:alarm".equals(record.getType())) {
                type = "一键报警";
                eventDesc = String.format("[%s]%s求救！", Strings.nullToEmpty(record.getAreaName()), record.getName());
            } else if ("stayAlarm".equals(record.getType())) {
                type = "滞留报警";
                String detail = record.getDetail();
                JsonObject detailObj = new JsonParser().parse(detail).getAsJsonObject();
                String railName = detailObj.get("railName").getAsString();
                eventDesc = String.format("[%s]%s滞留！", railName, record.getName());
            } else if ("lackNum".equals(record.getType())) {
                type = "缺员报警";
                String detail = record.getDetail();
                JsonObject detailObj = new JsonParser().parse(detail).getAsJsonObject();
                String railName = detailObj.get("railName").getAsString();
                eventDesc = String.format("[%s]缺员！", railName);
            } else if ("overNum".equals(record.getType())) {
                type = "超员报警";
                String detail = record.getDetail();
                JsonObject detailObj = new JsonParser().parse(detail).getAsJsonObject();
                String railName = detailObj.get("railName").getAsString();
                eventDesc = String.format("[%s]超员！", railName);
            } else if ("stillAlarm".equals(record.getType())) {
                type = "静止报警";
                String detail = record.getDetail();
                JsonObject detailObj = new JsonParser().parse(detail).getAsJsonObject();
                String areaName = detailObj.get("areaName").getAsString();
                eventDesc = String.format("[%s]%s静止！", areaName, record.getName());
            } else {
                return null;
            }
            bean.setTitle(type);
            bean.setType(type);
            bean.setContent(eventDesc);
            return bean;
        }
        return null;
    }

    public static String getSignature(Map<String, Object> paramMap, String secret) {

        Map<String, Object> sortMap = new TreeMap<String, Object>();
        sortMap.putAll(paramMap);
        // 以k1=v1&k2=v2...方式拼接参数
        StringBuilder builder = new StringBuilder();
        for (Map.Entry<String, Object> s : sortMap.entrySet()) {
            String k = s.getKey();
            Object v = s.getValue();
            if (v == null) {// 过滤空值
                continue;
            }
            builder.append(k).append(v);
        }
        String paJson = builder.toString();
        // LOGGER.info("beforeconvertUnicode: " + paJson);
        paJson = convertUnicode(paJson);
        return Md5Util.md5(secret + paJson).toUpperCase();
    }

    public static final String REGEX = "[\u4e00-\u9fa5]";
    public static final String REGEX2 = "[\ufe30-\uffa0]";
    public static final String REGEX3 = "[\u3002\uff1f\uff01\uff0c\u3001\uff1b\uff1a\u201c\u201d\u2018\u2019\uff08\uff09\u300a\u300b\u3008\u3009\u3010\u3011\u300e\u300f\u300c\u300d\ufe43\ufe44\u3014\u3015\u2026\u2014\uff5e\ufe4f\uffe5]";
    public static final String REGEX4 = "\u0026\u0023\u0031\u0038\u0033\u003b";

    public static String convertUnicode(String str) {
        str = str.replaceAll("·", "");

        Pattern pattern = Pattern.compile(REGEX);
        Matcher matcher = pattern.matcher(str);
        while (matcher.find()) {
            String chinese = matcher.group(0) + "";
            str = str.replace(chinese, gbEncoding(chinese));
        }
        Pattern pattern2 = Pattern.compile(REGEX2);
        Matcher matcher2 = pattern2.matcher(str);
        while (matcher2.find()) {
            String chinese = matcher2.group(0) + "";
            str = str.replace(chinese, gbEncoding(chinese));
        }
        Pattern pattern3 = Pattern.compile(REGEX3);
        Matcher matcher3 = pattern3.matcher(str);
        while (matcher3.find()) {
            String chinese = matcher3.group(0) + "";
            str = str.replace(chinese, gbEncoding(chinese));
        }
        return str;
    }

    // 中文转Unicode
    public static String gbEncoding(String gbString) { // gbString = "测试"
        char[] utfBytes = gbString.toCharArray(); // utfBytes = [测, 试]
        String unicodeBytes = "";
        for (int byteIndex = 0; byteIndex < utfBytes.length; byteIndex++) {
            String hexB = Integer.toHexString(utfBytes[byteIndex]); // 转换为16进制整型字符串
            if (hexB.length() <= 2) {
                hexB = "00" + hexB;
            }
            unicodeBytes = unicodeBytes + "\\u" + hexB;
        }
        // System.out.println("unicodeBytes is: " + unicodeBytes);
        return unicodeBytes;
    }

    @Override
    public String getHttpIpPort(String ipPort) {
        BaseConfig protocolConfig = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_API_SYNC_PROTOCOL);
        //默认http
        String protocol = "http://";
        if (protocolConfig != null) {
            String configValue = protocolConfig.getValue();
            if (configValue != null && (configValue.contains("https") || configValue.contains("HTTPS"))) {
                protocol = "https://";
            }
        }
        return protocol + ipPort;
    }

    private String getHttpIpPort(String ipPort, Long tenentId, String orgCode) {
        BaseConfig protocolConfig = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_API_SYNC_PROTOCOL);
        //默认http
        String protocol = "http://";
        if (protocolConfig != null) {
            String configValue = protocolConfig.getValue();
            if (configValue != null && (configValue.contains("https") || configValue.contains("HTTPS"))) {
                protocol = "https://";
            }
        }
        return protocol + ipPort;
    }

    private String getApiHttpIpPort(String ipPort, Long tenentId, String orgCode) {
        ApiBaseConfigBean protocolConfig = configMapper.findConfig(tenentId, orgCode, BaseConfigCodes.LOCATE_API_SYNC_PROTOCOL);
        //默认http
        String protocol = "http://";
        if (protocolConfig != null) {
            String configValue = protocolConfig.getValue();
            if (configValue != null && (configValue.contains("https") || configValue.contains("HTTPS"))) {
                protocol = "https://";
            }
        }
        return protocol + ipPort;
    }

}
